JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.util.ObjectBuffer;
/**
* Separate implementation for serializing String arrays (instead of
* using {@link ObjectArrayDeserializer}.
* Used if (and only if) no custom value deserializers are used.
*/
@JacksonStdImpl
public final class StringArrayDeserializer
extends StdDeserializer<String[]>
implements ContextualDeserializer
{
private static final long serialVersionUID = -7589512013334920693L;
public final static StringArrayDeserializer instance = new StringArrayDeserializer();
/**
* Value serializer to use, if not the standard one (which is inlined)
*/
protected JsonDeserializer<String> _elementDeserializer;
public StringArrayDeserializer() {
super(String[].class);
_elementDeserializer = null;
}
@SuppressWarnings("unchecked")
// [JACKSON-620] Empty String can become null...
if ((jp.getCurrentToken() == JsonToken.VALUE_STRING)
&& ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
String str = jp.getText();
if (str.length() == 0) {
return null;
}
}
throw ctxt.mappingException(_valueClass);
}
return new String[] { (jp.getCurrentToken() == JsonToken.VALUE_NULL) ? null : _parseString(jp, ctxt) };
}
/**
* Contextualization is needed to see whether we can "inline" deserialization
* of String values, or if we have to use separate value deserializer.
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException
{
JsonDeserializer<?> deser = _elementDeserializer;
// #125: May have a content converter
deser = findConvertingContentDeserializer(ctxt,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* For now, File objects get serialized by just outputting
* absolute (but not canonical) name as String value
*/
public class FileSerializer
extends StdScalarSerializer<File>
{
public FileSerializer() { super(File.class); }
@Override
public void serialize(File value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
jgen.writeString(value.getAbsolutePath());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectStringFormat(typeHint);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> {
kind = Std.STD_JAVA_TYPE;
} else if (rawType == Currency.class) {
kind = Std.STD_CURRENCY;
} else if (rawType == Pattern.class) {
kind = Std.STD_PATTERN;
} else if (rawType == Locale.class) {
kind = Std.STD_LOCALE;
} else if (rawType == Charset.class) {
kind = Std.STD_CHARSET;
} else if (rawType == TimeZone.class) {
kind = Std.STD_TIME_ZONE;
} else if (rawType == InetAddress.class) {
kind = Std.STD_INET_ADDRESS;
} else if (rawType == InetSocketAddress.class) {
kind = Std.STD_INET_SOCKET_ADDRESS;
} else {
return null;
}
return new Std(rawType, kind);
}
/*
/**********************************************************
/* Deserializer implementations
/**********************************************************
*/
@SuppressWarnings("unchecked")
@Override
public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Issue#381
if (jp.getCurrentToken() == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final T value = deserialize(jp, ctxt);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
}
return value;
}
// 22-Sep-2012, tatu: For 2.1, use this new method, may force coercion:
String text = jp.getValueAsString();
if (text != null) { // has String representation
if (text.length() == 0 || (text = text.trim()).length() == 0) {
// 04-Feb-2013, tatu: Usually should become null; but not always
return _deserializeFromEmptyString();
}
Exception cause = null;
try {
T result = _deserialize(text, ctxt
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>);
if (result != null) {
return result;
}
} catch (IllegalArgumentException iae) {
cause = iae;
}
String msg = "not a valid textual representation";
if (cause != null) {
msg += "problem: "+cause.getMessage();
}
JsonMappingException e = ctxt.weirdStringException(text, _valueClass, msg);
if (cause != null) {
e.initCause(cause);
}
throw e;
// nothing to do here, yet? We'll fail anyway
}
if (jp.getCurrentToken() == JsonToken.VALUE_EMBEDDED_OBJECT) {
// Trivial cases; null to null, instance of type itself returned as is
Object ob = jp.getEmbeddedObject();
if (ob == null) {
return null;
}
if (_valueClass.isAssignableFrom(ob.getClass())) {
return (T) ob;
}
return _deserializeEmbedded(ob, ctxt);
}
throw ctxt.mappingException(_valueClass);
}
protected abstract T _deserialize(String value, DeserializationContext ctxt) throws IOException;
protected T _deserializeEmbedded(Object ob, DeserializationContext ctxt) throws IOException {
// default impl: error out
throw ctxt.mappingException("Don't know how to convert embedded Object of type "+ob.getClass().getName()+" into "+_valueClass.getName());
}
protected T _deserializeFromEmptyString() throws IOException {
return null;
}
/*
/**********************************************************
/* A general-purpose implementation
/**********************************************************
*/
/**
* "Chameleon" deserializer that works on simple types that are deserialized
* from a simple String.
*
* @since 2.4
*/
public static class Std extends FromStringDeserializer<Object>
{
private static final long serialVersionUID = 1;
public final static int STD_FILE = 1;
public final static int STD_URL = 2;
public final static int STD_URI = 3;
public final static int STD_CLASS = 4;
public final static int STD_JAVA_TYPE = 5;
public final static int STD_CURRENCY = 6;
public final static int STD_PATTERN = 7;
public final static int STD_LOCALE = 8;
public
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> final static int STD_CHARSET = 9;
public final static int STD_TIME_ZONE = 10;
public final static int STD_INET_ADDRESS = 11;
public final static int STD_INET_SOCKET_ADDRESS = 12;
protected final int _kind;
protected Std(Class<?> valueType, int kind) {
super(valueType);
_kind = kind;
}
@Override
protected Object _deserialize(String value, DeserializationContext ctxt) throws IOException
{
switch (_kind) {
case STD_FILE:
return new File(value);
case STD_URL:
return new URL(value);
case STD_URI:
return URI.create(value);
case STD_CLASS:
try {
return ctxt.findClass(value);
} catch (Exception e) {
throw ctxt.instantiationException(_valueClass, ClassUtil.getRootCause(e));
}
case STD_JAVA_TYPE:
return ctxt.getTypeFactory().constructFromCanonical(value);
case STD_CURRENCY:
// will throw IAE if unknown:
return Currency.getInstance(value);
case STD_PATTERN:
// will throw IAE (or its subclass) if malformed
return Pattern.compile(value);
case STD_LOCALE:
{
int ix = value.indexOf('_');
if (ix < 0) { // single argument
return new Locale(value);
}
String first = value.substring(0, ix);
value = value.substring(ix+1);
ix = value.indexOf('_');
if (ix < 0) { // two pieces
return new Locale(first, value);
}
String second = value.substring(0, ix);
return new Locale(first, second, value.substring(ix+1));
}
case STD_CHARSET:
return Charset.forName(value);
case STD_TIME_ZONE:
return TimeZone.getTimeZone(value);
case STD_INET_ADDRESS:
return InetAddress.getByName(value);
case STD_INET_SOCKET_ADDRESS:
if (value.startsWith("[")) {
// bracketed IPv6 (with port number)
int i = value.lastIndexOf(']');
if (i == -1) {
throw new InvalidFormatException("Bracketed
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.exc;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Specialized sub-class of {@link JsonMappingException}
* that is used when the underlying problem appears to be that
* of bad formatting of a value to deserialize.
*
* @since 2.1
*/
public class InvalidFormatException extends JsonMappingException
{
private static final long serialVersionUID = 1L; // silly Eclipse, warnings
/**
* Underlying value that could not be deserialized into
* target type, if available.
*/
protected final Object _value;
/**
* Intended target type (type-erased class) that value could not
* be deserialized into, if known.
*/
protected final Class<?> _targetType;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
public InvalidFormatException(String msg,
Object value, Class<?> targetType)
{
super(msg);
_value = value;
_targetType = targetType;
}
public InvalidFormatException(String msg, JsonLocation loc,
Object value, Class<?> targetType)
{
super(msg, loc);
_value = value;
_targetType = targetType;
}
public static InvalidFormatException from(JsonParser jp, String msg,
Object value, Class<?> targetType)
{
return new InvalidFormatException(msg, jp.getTokenLocation(),
value, targetType);
}
/*
/**********************************************************
/* Additional accessors
/**********************************************************
*/
/**
* Accessor for checking source value (String, Number usually) that could not
* be deserialized into target type ({@link #getTargetType}).
* Note that value may not be available, depending on who throws the exception
* and when.
*/
public Object getValue() {
return _value;
}
/**
* Accessor for checking target type of value ({@link #getValue} that failed
* to deserialize.
* Note that type may not be available, depending on who throws the exception
* and when.
*/
public Class<?> getTargetType() {
return _targetType;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>;
_delegateDeserializer = (JsonDeserializer<Object>) delegateDeserializer;
}
/**
* Method used for creating resolved contextual instances. Must be
* overridden when sub-classing.
*/
protected StdDelegatingDeserializer<T> withDelegate(Converter<Object,T> converter,
JavaType delegateType, JsonDeserializer<?> delegateDeserializer)
{
if (getClass() != StdDelegatingDeserializer.class) {
throw new IllegalStateException("Sub-class "+getClass().getName()+" must override 'withDelegate'");
}
return new StdDelegatingDeserializer<T>(converter, delegateType, delegateDeserializer);
}
/*
/**********************************************************
/* Contextualization
/**********************************************************
*/
@Override
public void resolve(DeserializationContext ctxt)
throws JsonMappingException
{
if (_delegateDeserializer != null && _delegateDeserializer instanceof ResolvableDeserializer) {
((ResolvableDeserializer) _delegateDeserializer).resolve(ctxt);
}
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
throws JsonMappingException
{
// First: if already got serializer to delegate to, contextualize it:
if (_delegateDeserializer != null) {
JsonDeserializer<?> deser = ctxt.handleSecondaryContextualization(_delegateDeserializer, property);
if (deser != _delegateDeserializer) {
return withDelegate(_converter, _delegateType, deser);
}
return this;
}
// Otherwise: figure out what is the fully generic delegate type, then find deserializer
JavaType delegateType = _converter.getInputType(ctxt.getTypeFactory());
return withDelegate(_converter, delegateType,
ctxt.findContextualValueDeserializer(delegateType, property));
}
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
@Override
public JsonDeserializer<?> getDelegatee() {
return _delegateDeserializer;
}
@Override
public Class<?> handledType() {
return _delegateDeserializer.handledType();
}
/*
/**********************************************************
/* Serialization
/**********************************************************
*/
@Override
public T deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
Object delegateValue = _delegateDeserializer.deserialize(jp, ctxt);
if (delegateValue == null) {
return null;
}
return convertValue(delegateValue);
}
@Override
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
Enum<?> result = _resolver.getEnum(ix);
if (result != null) {
return result;
}
} catch (NumberFormatException e) {
// fine, ignore, was not an integer
}
}
}
if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
throw ctxt.weirdStringException(name, _resolver.getEnumClass(),
"value not one of declared Enum instance names: "+_resolver.getEnums());
}
return null;
}
private final Enum<?> _deserializeOther(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken curr = jp.getCurrentToken();
// Issue#381
if (curr == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Enum<?> parsed = deserialize(jp, ctxt);
curr = jp.nextToken();
if (curr != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single '" + _resolver.getEnumClass().getName() + "' value but there was more than a single value in the array");
}
return parsed;
}
throw ctxt.mappingException(_resolver.getEnumClass());
}
/*
/**********************************************************
/* Additional helper classes
/**********************************************************
*/
/**
* Deserializer that uses a single-String static factory method
* for locating Enum values by String id.
*/
protected static class FactoryBasedDeserializer
extends StdScalarDeserializer<Object>
{
private static final long serialVersionUID = -7775129435872564122L;
protected final Class<?> _enumClass;
// Marker type; null if String expected; otherwise numeric wrapper
protected final Class<?> _inputType;
protected final Method _factory;
public FactoryBasedDeserializer(Class<?> cls, AnnotatedMethod f,
Class<?> inputType)
{
super(Enum.class);
_enumClass = cls;
_factory = f.getAnnotated();
_inputType = inputType;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, Json
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>ProcessingException
{
// couple of accepted types...
Object value;
if (_inputType == null) {
value = jp.getText();
} else if (_inputType == Integer.class) {
value = Integer.valueOf(jp.getValueAsInt());
} else if (_inputType == Long.class) {
value = Long.valueOf(jp.getValueAsLong());
} else {
throw ctxt.mappingException(_enumClass);
}
try {
return _factory.invoke(_enumClass, value);
} catch (Exception e) {
Throwable t = ClassUtil.getRootCause(e);
if (t instanceof IOException) {
throw (IOException) t;
}
throw ctxt.instantiationException(_enumClass, t);
}
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.exc;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Base class for {@link JsonMappingException}s that are specifically related
* to problems related to binding an individual property.
*
* @since 2.3
*/
@SuppressWarnings("serial")
public abstract class PropertyBindingException
extends JsonMappingException
{
/**
* Class that does not contain mapping for the unrecognized property.
*/
protected final Class<?> _referringClass;
/**
*<p>
* Note: redundant information since it is also included in the
* reference path.
*/
protected final String _propertyName;
/**
* Set of ids of properties that are known for the type, if this
* can be statically determined.
*/
protected final Collection<Object> _propertyIds;
/**
* Lazily constructed description of known properties, used for
* constructing actual message if and as needed.
*/
protected transient String _propertiesAsString;
protected PropertyBindingException(String msg, JsonLocation loc,
Class<?> referringClass, String propName,
Collection<Object> propertyIds)
{
super(msg, loc);
_referringClass = referringClass;
_propertyName = propName;
_propertyIds = propertyIds;
}
/*
/**********************************************************
/* Overrides
/**********************************************************
*/
private final static int MAX_DESC_LENGTH = 200;
@Override
public String getMessageSuffix()
{
String suffix = _propertiesAsString;
if (suffix == null && _propertyIds != null) {
StringBuilder sb = new StringBuilder(100);
int len = _propertyIds.size();
if (len == 1) {
sb.append(" (one known property: \"");
sb.append(String.valueOf(_propertyIds.iterator().next()));
sb.append('"');
} else {
sb.append(" (").append(len).append(" known properties: ");
Iterator<Object> it = _propertyIds.iterator();
while (it.hasNext()) {
sb.append('"');
sb.append(String.valueOf
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> MyTokenizer tokens)
{
try {
return ClassUtil.findClass(className);
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw _problem(tokens, "Can not locate class '"+className+"', problem: "+e.getMessage());
}
}
protected IllegalArgumentException _problem(MyTokenizer tokens, String msg)
{
return new IllegalArgumentException("Failed to parse type '"+tokens.getAllInput()
+"' (remaining: '"+tokens.getRemainingInput()+"'): "+msg);
}
final static class MyTokenizer
extends StringTokenizer
{
protected final String _input;
protected int _index;
protected String _pushbackToken;
public MyTokenizer(String str) {
super(str, "<,>", true);
_input = str;
}
@Override
public boolean hasMoreTokens() {
return (_pushbackToken != null) || super.hasMoreTokens();
}
@Override
public String nextToken() {
String token;
if (_pushbackToken != null) {
token = _pushbackToken;
_pushbackToken = null;
} else {
token = super.nextToken();
}
_index += token.length();
return token;
}
public void pushBack(String token) {
_pushbackToken = token;
_index -= token.length();
}
public String getAllInput() { return _input; }
public String getUsedInput() { return _input.substring(0, _index); }
public String getRemainingInput() { return _input.substring(_index); }
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>AsIndex;
}
/**
* Factory method used by {@link com.fasterxml.jackson.databind.ser.BasicSerializerFactory}
* for constructing serializer instance of Enum types.
*
* @since 2.1
*/
public static EnumSerializer construct(Class<Enum<?>> enumClass, SerializationConfig config,
BeanDescription beanDesc, JsonFormat.Value format)
{
// [JACKSON-212]: If toString() is to be used instead, leave EnumValues null
EnumValues v = EnumValues.construct(config, enumClass);
Boolean serializeAsIndex = _isShapeWrittenUsingIndex(enumClass, format, true);
return new EnumSerializer(v, serializeAsIndex);
}
/**
* To support some level of per-property configuration, we will need
* to make things contextual. We are limited to "textual vs index"
* choice here, however.
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException
{
if (property != null) {
JsonFormat.Value format = prov.getAnnotationIntrospector().findFormat((Annotated) property.getMember());
if (format != null) {
Boolean serializeAsIndex = _isShapeWrittenUsingIndex(property.getType().getRawClass(), format, false);
if (serializeAsIndex != _serializeAsIndex) {
return new EnumSerializer(_values, serializeAsIndex);
}
}
}
return this;
}
/*
/**********************************************************
/* Extended API for Jackson databind core
/**********************************************************
*/
public EnumValues getEnumValues() { return _values; }
/*
/**********************************************************
/* Actual serialization
/**********************************************************
*/
@Override
public final void serialize(Enum<?> en, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
// [JACKSON-684]: serialize as index?
if (_serializeAsIndex(provider)) {
jgen.writeNumber(en.ordinal());
return;
}
jgen.writeString(_values.serializedValueFor(en));
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
// [JACKSON-684]: serialize as index?
if (_serializeAsIndex(provider))
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> {
return createSchemaNode("integer", true);
}
ObjectNode objectNode = createSchemaNode("string", true);
if (typeHint != null) {
JavaType type = provider.constructType(typeHint);
if (type.isEnumType()) {
ArrayNode enumNode = objectNode.putArray("enum");
for (SerializableString value : _values.values()) {
enumNode.add(value.getValue());
}
}
}
return objectNode;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
// [JACKSON-684]: serialize as index?
if (visitor.getProvider().isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) {
JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
if (v2 != null) { // typically serialized as a small number (byte or int)
v2.numberType(JsonParser.NumberType.INT);
}
} else {
JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint);
if (typeHint != null && stringVisitor != null) {
if (typeHint.isEnumType()) {
Set<String> enums = new LinkedHashSet<String>();
for (SerializableString value : _values.values()) {
enums.add(value.getValue());
}
stringVisitor.enumTypes(enums);
}
}
}
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
protected final boolean _serializeAsIndex(SerializerProvider provider)
{
if (_serializeAsIndex != null) {
return _serializeAsIndex.booleanValue();
}
return provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX);
}
/**
* Helper method called to check whether
*/
protected static Boolean _isShapeWrittenUsingIndex(Class<?> enumClass,
JsonFormat.Value format, boolean fromClass)
{
JsonFormat.Shape shape = (format == null) ? null : format.getShape();
if (shape == null) {
return null;
}
if (shape == Shape.ANY || shape == Shape.SCALAR) { // i
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
// Hmmh. What should it be? Ideally should probably indicate BIG_DECIMAL
// to ensure no information is lost? But probably won't work that well...
JsonNumberFormatVisitor v2 = visitor.expectNumberFormat(typeHint);
if (v2 != null) {
v2.numberType(JsonParser.NumberType.BIG_DECIMAL);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.exc;
import java.util.*;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Specialized {@link JsonMappingException} sub-class specifically used
* to indicate problems due to encountering a JSON property that could
* not be mapped to an Object property (via getter, constructor argument
* or field).
*/
public class UnrecognizedPropertyException
extends PropertyBindingException
{
private static final long serialVersionUID = 1L;
public UnrecognizedPropertyException(String msg, JsonLocation loc,
Class<?> referringClass, String propName,
Collection<Object> propertyIds)
{
super(msg, loc, referringClass, propName, propertyIds);
}
/**
* Factory method used for constructing instances of this exception type.
*
* @param jp Underlying parser used for reading input being used for data-binding
* @param fromObjectOrClass Reference to either instance of problematic type (
* if available), or if not, type itself
* @param propertyName Name of unrecognized property
* @param propertyIds (optional, null if not available) Set of properties that
* type would recognize, if completely known: null if set can not be determined.
*/
public static UnrecognizedPropertyException from(JsonParser jp,
Object fromObjectOrClass, String propertyName,
Collection<Object> propertyIds)
{
if (fromObjectOrClass == null) {
throw new IllegalArgumentException();
}
Class<?> ref;
if (fromObjectOrClass instanceof Class<?>) {
ref = (Class<?>) fromObjectOrClass;
} else {
ref = fromObjectOrClass.getClass();
}
String msg = "Unrecognized field \""+propertyName+"\" (class "+ref.getName()+"), not marked as ignorable";
UnrecognizedPropertyException e = new UnrecognizedPropertyException(msg,
jp.getCurrentLocation(), ref, propertyName, propertyIds);
// but let's also ensure path includes this last (missing) segment
e.prependPath(fromObjectOrClass, propertyName);
return e;
}
/**
* @deprecated Since 2.3, use {@link #getPropertyName} instead.
*/
@Deprecated
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> = roid.referringProperties(); iterator.hasNext();) {
Referring referring = iterator.next();
exception.addUnresolvedId(roid.getKey().key, referring.getBeanType(), referring.getLocation());
}
}
}
if (exception != null) {
throw exception;
}
}
/*
/**********************************************************
/* Abstract methods impls, other factory methods
/**********************************************************
*/
@SuppressWarnings("unchecked")
@Override
public JsonDeserializer<Object> deserializerInstance(Annotated ann, Object deserDef)
throws JsonMappingException
{
if (deserDef == null) {
return null;
}
JsonDeserializer<?> deser;
if (deserDef instanceof JsonDeserializer) {
deser = (JsonDeserializer<?>) deserDef;
} else {
/* Alas, there's no way to force return type of "either class
* X or Y" -- need to throw an exception after the fact
*/
if (!(deserDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead");
}
Class<?> deserClass = (Class<?>)deserDef;
// there are some known "no class" markers to consider too:
if (deserClass == JsonDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) {
return null;
}
if (!JsonDeserializer.class.isAssignableFrom(deserClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>");
}
HandlerInstantiator hi = _config.getHandlerInstantiator();
deser = (hi == null) ? null : hi.deserializerInstance(_config, ann, deserClass);
if (deser == null) {
deser = (JsonDeserializer<?>) ClassUtil.createInstance(deserClass,
_config.canOverrideAccessModifiers());
}
}
// First: need to resolve
if (deser instanceof ResolvableDeserializer) {
((ResolvableDeserializer) deser).resolve(this);
}
return (JsonDeserializer<Object>) deser;
}
@Override
public final KeyDeserializer keyDeserializerInstance(Annotated ann, Object deserDef)
throws JsonMappingException
{
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(): first argument not of type String or Object, but "+type.getName());
}
}
return _anySetterMethod;
}
@Override
public Map<Object, AnnotatedMember> findInjectables() {
return _injectables;
}
@Override
public List<AnnotatedConstructor> getConstructors() {
return _classInfo.getConstructors();
}
@Override
public Object instantiateBean(boolean fixAccess)
{
AnnotatedConstructor ac = _classInfo.getDefaultConstructor();
if (ac == null) {
return null;
}
if (fixAccess) {
ac.fixAccess();
}
try {
return ac.getAnnotated().newInstance();
} catch (Exception e) {
Throwable t = e;
while (t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) throw (Error) t;
if (t instanceof RuntimeException) throw (RuntimeException) t;
throw new IllegalArgumentException("Failed to instantiate bean of type "+_classInfo.getAnnotated().getName()+": ("+t.getClass().getName()+") "+t.getMessage(), t);
}
}
/*
/**********************************************************
/* Simple accessors, extended
/**********************************************************
*/
@Override
public AnnotatedMethod findMethod(String name, Class<?>[] paramTypes) {
return _classInfo.findMethod(name, paramTypes);
}
/*
/**********************************************************
/* General per-class annotation introspection
/**********************************************************
*/
@Override
public JsonFormat.Value findExpectedFormat(JsonFormat.Value defValue)
{
if (_annotationIntrospector != null) {
JsonFormat.Value v = _annotationIntrospector.findFormat(_classInfo);
if (v != null) {
return v;
}
}
return defValue;
}
/*
/**********************************************************
/* Introspection for serialization
/**********************************************************
*/
@Override
public Converter<Object,Object> findSerializationConverter()
{
if (_annotationIntrospector == null) {
return null;
}
return _createConverter(_annotationIntrospector.findSerializationConverter(_classInfo));
}
/**
* Method for determining whether null properties should be written
* out for a Bean of introspected type. This is based on global
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Deprecated // since 2.3 -- use 'withSimpleName' instead if need be
public SettableBeanProperty withName(String simpleName) {
return withName(new PropertyName(simpleName));
}
public void setManagedReferenceName(String n) {
_managedReferenceName = n;
}
public void setObjectIdInfo(ObjectIdInfo objectIdInfo) {
_objectIdInfo = objectIdInfo;
}
public void setViews(Class<?>[] views) {
if (views == null) {
_viewMatcher = null;
} else {
_viewMatcher = ViewMatcher.construct(views);
}
}
/**
* Method used to assign index for property.
*/
public void assignIndex(int index) {
if (_propertyIndex != -1) {
throw new IllegalStateException("Property '"+getName()+"' already had index ("+_propertyIndex+"), trying to assign "+index);
}
_propertyIndex = index;
}
/*
/**********************************************************
/* BeanProperty impl
/**********************************************************
*/
@Override
public final String getName() {
return _propName.getSimpleName();
}
@Override
public PropertyName getFullName() {
return _propName;
}
@Override
public boolean isRequired() { return _metadata.isRequired(); }
@Override
public PropertyMetadata getMetadata() { return _metadata; }
@Override
public JavaType getType() { return _type; }
@Override
public PropertyName getWrapperName() {
return _wrapperName;
}
@Override
public abstract <A extends Annotation> A getAnnotation(Class<A> acls);
@Override
public abstract AnnotatedMember getMember();
@Override
public <A extends Annotation> A getContextAnnotation(Class<A> acls) {
return _contextAnnotations.get(acls);
}
@Override
public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor)
throws JsonMappingException
{
if (isRequired()) {
objectVisitor.property(this);
} else {
objectVisitor.optionalProperty(this);
}
}
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
protected final Class<?> getDeclaringClass() {
return getMember().getDeclaringClass();
}
public String getManagedReferenceName() { return _
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>AsIOE(Exception e, Object value)
throws IOException
{
if (e instanceof IllegalArgumentException) {
String actType = (value == null) ? "[NULL]" : value.getClass().getName();
StringBuilder msg = new StringBuilder("Problem deserializing property '").append(getName());
msg.append("' (expected type: ").append(getType());
msg.append("; actual type: ").append(actType).append(")");
String origMsg = e.getMessage();
if (origMsg != null) {
msg.append(", problem: ").append(origMsg);
} else {
msg.append(" (no error message provided)");
}
throw new JsonMappingException(msg.toString(), null, e);
}
_throwAsIOE(e);
}
protected IOException _throwAsIOE(Exception e)
throws IOException
{
if (e instanceof IOException) {
throw (IOException) e;
}
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
// let's wrap the innermost problem
Throwable th = e;
while (th.getCause() != null) {
th = th.getCause();
}
throw new JsonMappingException(th.getMessage(), null, th);
}
@Override public String toString() { return "[property '"+getName()+"']"; }
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Type, keyDeserializer, valueDeserializer, _valueTypeDeserializer);
}
/**
* Method called to finalize setup of this deserializer,
* when it is known for which property deserializer is needed for.
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException
{
// note: instead of finding key deserializer, with enums we actually
// work with regular deserializers (less code duplication; but not
// quite as clean as it ought to be)
JsonDeserializer<?> kd = _keyDeserializer;
if (kd == null) {
kd = ctxt.findContextualValueDeserializer(_mapType.getKeyType(), property);
}
JsonDeserializer<?> vd = _valueDeserializer;
if (vd == null) {
vd = ctxt.findContextualValueDeserializer(_mapType.getContentType(), property);
} else { // if directly assigned, probably not yet contextual, so:
vd = ctxt.handleSecondaryContextualization(vd, property);
}
TypeDeserializer vtd = _valueTypeDeserializer;
if (vtd != null) {
vtd = vtd.forProperty(property);
}
return withResolved(kd, vd, vtd);
}
/**
* Because of costs associated with constructing Enum resolvers,
* let's cache instances by default.
*/
@Override
public boolean isCachable() { return true; }
/*
/**********************************************************
/* Actual deserialization
/**********************************************************
*/
@Override
public EnumMap<?,?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
// Ok: must point to START_OBJECT
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.mappingException(EnumMap.class);
}
EnumMap result = constructMap();
final JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
while ((jp.nextToken()) != JsonToken.END_OBJECT) {
Enum<?> key = _keyDeserializer.deserialize(jp, ctxt);
if (key == null) {
if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
String value = null;
try { // bit ugly, but will
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> have to do; works with usual scalars
if (jp.hasCurrentToken()) {
value = jp.getText();
}
} catch (Exception e) { }
throw ctxt.weirdStringException(value, _enumClass, "value not one of declared Enum instance names");
}
/* 24-Mar-2012, tatu: Null won't work as a key anyway, so let's
* just skip the entry then. But we must skip the value then.
*/
jp.nextToken();
jp.skipChildren();
continue;
}
// And then the value...
JsonToken t = jp.nextToken();
/* note: MUST check for nulls separately: deserializers will
* not handle them (and maybe fail or return bogus data)
*/
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
result.put(key, value);
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
}
private EnumMap<?,?> constructMap() {
return new EnumMap(_enumClass);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
public class AtomicReferenceDeserializer
extends StdDeserializer<AtomicReference<?>>
implements ContextualDeserializer
{
private static final long serialVersionUID = 1L;
/**
* Type of value that we reference
*/
protected final JavaType _referencedType;
protected final TypeDeserializer _valueTypeDeserializer;
protected final JsonDeserializer<?> _valueDeserializer;
/**
* @param referencedType Parameterization of this reference
*/
public AtomicReferenceDeserializer(JavaType referencedType) {
this(referencedType, null, null);
}
public AtomicReferenceDeserializer(JavaType referencedType, TypeDeserializer typeDeser, JsonDeserializer<?> deser)
{
super(AtomicReference.class);
_referencedType = referencedType;
_valueDeserializer = deser;
_valueTypeDeserializer = typeDeser;
}
public AtomicReferenceDeserializer withResolved(TypeDeserializer typeDeser, JsonDeserializer<?> valueDeser) {
return new AtomicReferenceDeserializer(_referencedType, typeDeser, valueDeser);
}
// Added in 2.3
@Override
public AtomicReference<?> getNullValue() {
return new AtomicReference<Object>();
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException
{
JsonDeserializer<?> deser = _valueDeserializer;
TypeDeserializer typeDeser = _valueTypeDeserializer;
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(_referencedType, property);
}
if (typeDeser != null) {
typeDeser = typeDeser.forProperty(property);
}
if (deser == _valueDeserializer && typeDeser == _valueTypeDeserializer) {
return this;
}
return withResolved(typeDeser, deser);
}
@Override
public AtomicReference<?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
/* 06-Nov-2013, tatu: Looks like the
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> canBeABeanType(Class<?> type)
{
// First: language constructs that ain't beans:
if (type.isAnnotation()) {
return "annotation";
}
if (type.isArray()) {
return "array";
}
if (type.isEnum()) {
return "enum";
}
if (type.isPrimitive()) {
return "primitive";
}
// Anything else? Seems valid, then
return null;
}
public static String isLocalType(Class<?> type, boolean allowNonStatic)
{
/* As per [JACKSON-187], GAE seems to throw SecurityExceptions
* here and there... and GAE itself has a bug, too
* (see []). Bah. So we need to catch some wayward exceptions on GAE
*/
try {
// one more: method locals, anonymous, are not good:
if (type.getEnclosingMethod() != null) {
return "local/anonymous";
}
/* But how about non-static inner classes? Can't construct
* easily (theoretically, we could try to check if parent
* happens to be enclosing... but that gets convoluted)
*/
if (!allowNonStatic) {
if (type.getEnclosingClass() != null) {
if (!Modifier.isStatic(type.getModifiers())) {
return "non-static member class";
}
}
}
}
catch (SecurityException e) { }
catch (NullPointerException e) { }
return null;
}
/**
* Method for finding enclosing class for non-static inner classes
*/
public static Class<?> getOuterClass(Class<?> type)
{
// as above, GAE has some issues...
try {
// one more: method locals, anonymous, are not good:
if (type.getEnclosingMethod() != null) {
return null;
}
if (!Modifier.isStatic(type.getModifiers())) {
return type.getEnclosingClass();
}
} catch (SecurityException e) { }
catch (NullPointerException e) { }
return null;
}
/**
* Helper method used to weed out dynamic Proxy types; types that do
* not expose concrete method API that we could use to figure out
* automatic Bean (
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> if ("int".equals(className)) return Integer.TYPE;
if ("long".equals(className)) return Long.TYPE;
if ("float".equals(className)) return Float.TYPE;
if ("double".equals(className)) return Double.TYPE;
if ("boolean".equals(className)) return Boolean.TYPE;
if ("byte".equals(className)) return Byte.TYPE;
if ("char".equals(className)) return Character.TYPE;
if ("short".equals(className)) return Short.TYPE;
if ("void".equals(className)) return Void.TYPE;
}
// Two-phase lookup: first using context ClassLoader; then default
Throwable prob = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
try {
return Class.forName(className, true, loader);
} catch (Exception e) {
prob = getRootCause(e);
}
}
try {
return Class.forName(className);
} catch (Exception e) {
if (prob == null) {
prob = getRootCause(e);
}
}
if (prob instanceof RuntimeException) {
throw (RuntimeException) prob;
}
throw new ClassNotFoundException(prob.getMessage(), prob);
}
/*
/**********************************************************
/* Method type detection methods
/**********************************************************
*/
public static boolean hasGetterSignature(Method m)
{
// First: static methods can't be getters
if (Modifier.isStatic(m.getModifiers())) {
return false;
}
// Must take no args
Class<?>[] pts = m.getParameterTypes();
if (pts != null && pts.length != 0) {
return false;
}
// Can't be a void method
if (Void.TYPE == m.getReturnType()) {
return false;
}
// Otherwise looks ok:
return true;
}
/*
/**********************************************************
/* Exception handling
/**********************************************************
*/
/**
* Method that can be used to find the "root cause", innermost
* of chained (wrapped) exceptions.
*/
public static Throwable getRootCause(Throwable t)
{
while (t.getCause() != null) {
t = t.getCause();
}
return t;
}
/**
* Method that will unwrap root causes of given
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> Throwable, and throw
* the innermost {@link Exception} or {@link Error} as is.
* This is useful in cases where mandatory wrapping is added, which
* is often done by Reflection API.
*/
public static void throwRootCause(Throwable t) throws Exception
{
t = getRootCause(t);
if (t instanceof Exception) {
throw (Exception) t;
}
throw (Error) t;
}
/**
* Method that will wrap 't' as an {@link IllegalArgumentException} if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void throwAsIAE(Throwable t)
{
throwAsIAE(t, t.getMessage());
}
/**
* Method that will wrap 't' as an {@link IllegalArgumentException} (and with
* specified message) if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void throwAsIAE(Throwable t, String msg)
{
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
if (t instanceof Error) {
throw (Error) t;
}
throw new IllegalArgumentException(msg, t);
}
/**
* Method that will locate the innermost exception for given Throwable;
* and then wrap it as an {@link IllegalArgumentException} if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void unwrapAndThrowAsIAE(Throwable t)
{
throwAsIAE(getRootCause(t));
}
/**
* Method that will locate the innermost exception for given Throwable;
* and then wrap it as an {@link IllegalArgumentException} if it
* is a checked exception; otherwise (runtime exception or error) throw as is
*/
public static void unwrapAndThrowAsIAE(Throwable t, String msg)
{
throwAsIAE(getRootCause(t), msg);
}
/*
/**********************************************************
/* Instantiation
/**********************************************************
*/
/**
* Method that can be called to try to create an instantiate of
* specified type. Instantiation is done using default no-argument
* constructor.
*
* @param canFixAccess Whether it is possible to try to change access
* rights of the default constructor (in
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> case it is not publicly
* accessible) or not.
*
* @throws IllegalArgumentException If instantiation fails for any reason;
* except for cases where constructor throws an unchecked exception
* (which will be passed as is)
*/
public static <T> T createInstance(Class<T> cls, boolean canFixAccess)
throws IllegalArgumentException
{
Constructor<T> ctor = findConstructor(cls, canFixAccess);
if (ctor == null) {
throw new IllegalArgumentException("Class "+cls.getName()+" has no default (no arg) constructor");
}
try {
return ctor.newInstance();
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+cls.getName()+", problem: "+e.getMessage());
return null;
}
}
public static <T> Constructor<T> findConstructor(Class<T> cls, boolean canFixAccess)
throws IllegalArgumentException
{
try {
Constructor<T> ctor = cls.getDeclaredConstructor();
if (canFixAccess) {
checkAndFixAccess(ctor);
} else {
// Has to be public...
if (!Modifier.isPublic(ctor.getModifiers())) {
throw new IllegalArgumentException("Default constructor for "+cls.getName()+" is not accessible (non-public?): not allowed to try modify access via Reflection: can not instantiate type");
}
}
return ctor;
} catch (NoSuchMethodException e) {
;
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e, "Failed to find default constructor of class "+cls.getName()+", problem: "+e.getMessage());
}
return null;
}
/*
/**********************************************************
/* Primitive type support
/**********************************************************
*/
/**
* Helper method used to get default value for wrappers used for primitive types
* (0 for Integer etc)
*/
public static Object defaultValue(Class<?> cls)
{
if (cls == Integer.TYPE) {
return Integer.valueOf(0);
}
if (cls == Long.TYPE) {
return Long.valueOf(0L);
}
if (cls == Boolean.TYPE) {
return Boolean.FALSE;
}
if (cls == Double.TYPE) {
return Double.valueOf(0.0);
}
if
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
/* JDK uses following fields to store information about actual Enumeration
* type for EnumSets, EnumMaps...
*/
enumSetTypeField = locateField(EnumSet.class, "elementType", Class.class);
enumMapTypeField = locateField(EnumMap.class, "elementType", Class.class);
}
@SuppressWarnings("unchecked")
public Class<? extends Enum<?>> enumTypeFor(EnumSet<?> set)
{
if (enumSetTypeField != null) {
return (Class<? extends Enum<?>>) get(set, enumSetTypeField);
}
throw new IllegalStateException("Can not figure out type for EnumSet (odd JDK platform?)");
}
@SuppressWarnings("unchecked")
public Class<? extends Enum<?>> enumTypeFor(EnumMap<?,?> set)
{
if (enumMapTypeField != null) {
return (Class<? extends Enum<?>>) get(set, enumMapTypeField);
}
throw new IllegalStateException("Can not figure out type for EnumMap (odd JDK platform?)");
}
private Object get(Object bean, Field field)
{
try {
return field.get(bean);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private static Field locateField(Class<?> fromClass, String expectedName, Class<?> type)
{
Field found = null;
// First: let's see if we can find exact match:
Field[] fields = fromClass.getDeclaredFields();
for (Field f : fields) {
if (expectedName.equals(f.getName()) && f.getType() == type) {
found = f;
break;
}
}
// And if not, if there is just one field with the type, that field
if (found == null) {
for (Field f : fields) {
if (f.getType() == type) {
// If more than one, can't choose
if (found != null) return null;
found = f;
}
}
}
if (found != null) { // it's non-public, need to force accessible
try {
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> instead.
*/
@Deprecated
public JsonFactory getJsonFactory() {
return _generatorFactory;
}
/**
* @since 2.2
*/
public JsonFactory getFactory() {
return _generatorFactory;
}
public TypeFactory getTypeFactory() {
return _config.getTypeFactory();
}
/**
* Diagnostics method that can be called to check whether this writer
* has pre-fetched serializer to use: pre-fetching improves performance
* when writer instances are reused as it avoids a per-call serializer
* lookup.
*
* @since 2.2
*/
public boolean hasPrefetchedSerializer() {
return _rootSerializer != null;
}
/**
* @since 2.3
*/
public ContextAttributes getAttributes() {
return _config.getAttributes();
}
/*
/**********************************************************
/* Serialization methods; ones from ObjectCodec first
/**********************************************************
*/
/**
* Method that can be used to serialize any Java value as
* JSON output, using provided {@link JsonGenerator}.
*/
public void writeValue(JsonGenerator jgen, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
// 10-Aug-2012, tatu: As per [Issue#12], may need to force PrettyPrinter settings, so:
_configureJsonGenerator(jgen);
if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE)
&& (value instanceof Closeable)) {
_writeCloseableValue(jgen, value, _config);
} else {
if (_rootType == null) {
_serializerProvider(_config).serializeValue(jgen, value);
} else {
_serializerProvider(_config).serializeValue(jgen, value, _rootType, _rootSerializer);
}
if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
jgen.flush();
}
}
}
/*
/**********************************************************
/* Serialization methods, others
/**********************************************************
*/
/**
* Method that can be used to serialize any Java value as
* JSON output, written to File provided.
*/
public void writeValue(File resultFile, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
_configAndWriteValue(_generatorFactory
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.createGenerator(resultFile, JsonEncoding.UTF8), value);
}
/**
* Method that can be used to serialize any Java value as
* JSON output, using output stream provided (using encoding
* {@link JsonEncoding#UTF8}).
*<p>
* Note: method does not close the underlying stream explicitly
* here; however, {@link JsonFactory} this mapper uses may choose
* to close the stream depending on its settings (by default,
* it will try to close it when {@link JsonGenerator} we construct
* is closed).
*/
public void writeValue(OutputStream out, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
_configAndWriteValue(_generatorFactory.createGenerator(out, JsonEncoding.UTF8), value);
}
/**
* Method that can be used to serialize any Java value as
* JSON output, using Writer provided.
*<p>
* Note: method does not close the underlying stream explicitly
* here; however, {@link JsonFactory} this mapper uses may choose
* to close the stream depending on its settings (by default,
* it will try to close it when {@link JsonGenerator} we construct
* is closed).
*/
public void writeValue(Writer w, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
_configAndWriteValue(_generatorFactory.createGenerator(w), value);
}
/**
* Method that can be used to serialize any Java value as
* a String. Functionally equivalent to calling
* {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter}
* and constructing String, but more efficient.
*<p>
* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
*/
@SuppressWarnings("resource")
public String writeValueAsString(Object value)
throws JsonProcessingException
{
// alas, we have to pull the recycler directly here...
SegmentedStringWriter sw = new SegmentedStringWriter(_generatorFactory._getBufferRecycler());
try {
_configAndWriteValue(_generatorFactory.createGenerator(sw), value);
} catch (JsonProcessingException e) { // to support [JACKSON-758]
throw e;
} catch (IOException e
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>) { // shouldn't really happen, but is declared as possibility so:
throw JsonMappingException.fromUnexpectedIOE(e);
}
return sw.getAndClear();
}
/**
* Method that can be used to serialize any Java value as
* a byte array. Functionally equivalent to calling
* {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream}
* and getting bytes, but more efficient.
* Encoding used will be UTF-8.
*<p>
* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
*/
@SuppressWarnings("resource")
public byte[] writeValueAsBytes(Object value)
throws JsonProcessingException
{
ByteArrayBuilder bb = new ByteArrayBuilder(_generatorFactory._getBufferRecycler());
try {
_configAndWriteValue(_generatorFactory.createGenerator(bb, JsonEncoding.UTF8), value);
} catch (JsonProcessingException e) { // to support [JACKSON-758]
throw e;
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
throw JsonMappingException.fromUnexpectedIOE(e);
}
byte[] result = bb.toByteArray();
bb.release();
return result;
}
/*
/**********************************************************
/* Other public methods
/**********************************************************
*/
/**
* Method for visiting type hierarchy for given type, using specified visitor.
* Visitation uses <code>Serializer</code> hierarchy and related properties
*<p>
* This method can be used for things like
* generating <a href="http://json-schema.org/">Json Schema</a>
* instance for specified type.
*
* @param type Type to generate schema for (possibly with generic signature)
*
* @since 2.2
*/
public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor)
throws JsonMappingException
{
if (type == null) {
throw new IllegalArgumentException("type must be provided");
}
_serializerProvider(_config).acceptJsonFormatVisitor(type, visitor);
}
public boolean canSerialize(Class<?> type) {
return _serializerProvider(_config).hasSerializerFor(type, null);
}
/**
* Method
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
try {
jgen.close();
} catch (IOException ioe) { }
}
}
}
/**
* Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
* method is to be called right after serialization has been called
*/
private final void _writeCloseable(JsonGenerator jgen, Object value, SerializationConfig cfg)
throws IOException, JsonGenerationException, JsonMappingException
{
Closeable toClose = (Closeable) value;
try {
if (_rootType == null) {
_serializerProvider(cfg).serializeValue(jgen, value);
} else {
_serializerProvider(cfg).serializeValue(jgen, value, _rootType, _rootSerializer);
}
JsonGenerator tmpJgen = jgen;
jgen = null;
tmpJgen.close();
Closeable tmpToClose = toClose;
toClose = null;
tmpToClose.close();
} finally {
/* Need to close both generator and value, as long as they haven't yet
* been closed
*/
if (jgen != null) {
/* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
* structures, which typically causes more damage.
*/
jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
try {
jgen.close();
} catch (IOException ioe) { }
}
if (toClose != null) {
try {
toClose.close();
} catch (IOException ioe) { }
}
}
}
/**
* Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
* method is to be called right after serialization has been called
*/
private final void _writeCloseableValue(JsonGenerator jgen, Object value, SerializationConfig cfg)
throws IOException, JsonGenerationException, JsonMappingException
{
Closeable toClose = (Closeable) value;
try {
if (_rootType == null) {
_serializerProvider(cfg).serializeValue(jgen, value);
} else {
_serializerProvider(cfg).serializeValue(j
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>gen, value, _rootType, _rootSerializer);
}
if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
jgen.flush();
}
Closeable tmpToClose = toClose;
toClose = null;
tmpToClose.close();
} finally {
if (toClose != null) {
try {
toClose.close();
} catch (IOException ioe) { }
}
}
}
/**
* Method called to locate (root) serializer ahead of time, if permitted
* by configuration. Method also is NOT to throw an exception if
* access fails.
*/
protected JsonSerializer<Object> _prefetchRootSerializer(
SerializationConfig config, JavaType valueType)
{
if (valueType == null || !_config.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH)) {
return null;
}
try {
return _serializerProvider(config).findTypedValueSerializer(valueType, true, null);
} catch (JsonProcessingException e) {
// need to swallow?
return null;
}
}
/**
* Helper method called to set or override settings of passed-in
* {@link JsonGenerator}
*
* @since 2.1
*/
private void _configureJsonGenerator(JsonGenerator jgen)
{
if (_prettyPrinter != null) {
PrettyPrinter pp = _prettyPrinter;
if (pp == NULL_PRETTY_PRINTER) {
jgen.setPrettyPrinter(null);
} else {
/* [JACKSON-851]: Better take care of stateful PrettyPrinters...
* like the DefaultPrettyPrinter.
*/
if (pp instanceof Instantiatable<?>) {
pp = (PrettyPrinter) ((Instantiatable<?>) pp).createInstance();
}
jgen.setPrettyPrinter(pp);
}
} else if (_config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
jgen.useDefaultPrettyPrinter();
}
if (_characterEscapes != null) {
jgen.setCharacterEscapes(_characterEscapes);
}
// [JACKSON-520]: add support for pass-through schema:
if (_schema != null) {
jgen.setSchema(_schema);
}
if (_cfgBigDecimalAsPlain) { // should only set
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.lang.reflect.Type;
import java.util.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* Intermediate base class for Lists, Collections and Arrays
* that contain static (non-dynamic) value types.
*/
public abstract class StaticListSerializerBase<T extends Collection<?>>
extends StdSerializer<T>
{
protected StaticListSerializerBase(Class<?> cls) {
super(cls, false);
}
@Override
public boolean isEmpty(T value) {
return (value == null) || (value.size() == 0);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("array", true).set("items", contentSchema());
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
acceptContentVisitor(visitor.expectArrayFormat(typeHint));
}
/*
/**********************************************************
/* Abstract methods for sub-classes to implement
/**********************************************************
*/
protected abstract JsonNode contentSchema();
protected abstract void acceptContentVisitor(JsonArrayFormatVisitor visitor)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>)
throws JsonMappingException
{
ExternalTypeHandler.Builder extTypes = null;
// if ValueInstantiator can use "creator" approach, need to resolve it here...
if (_valueInstantiator.canCreateFromObjectWith()) {
SettableBeanProperty[] creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
_propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps);
// also: need to try to resolve 'external' type ids...
for (SettableBeanProperty prop : _propertyBasedCreator.properties()) {
if (prop.hasValueTypeDeserializer()) {
TypeDeserializer typeDeser = prop.getValueTypeDeserializer();
if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
if (extTypes == null) {
extTypes = new ExternalTypeHandler.Builder();
}
extTypes.addExternal(prop, typeDeser);
}
}
}
}
UnwrappedPropertyHandler unwrapped = null;
for (SettableBeanProperty origProp : _beanProperties) {
SettableBeanProperty prop = origProp;
// May already have deserializer from annotations, if so, skip:
if (!prop.hasValueDeserializer()) {
// [Issue#125]: allow use of converters
JsonDeserializer<?> deser = findConvertingDeserializer(ctxt, prop);
if (deser == null) {
deser = findDeserializer(ctxt, prop.getType(), prop);
}
prop = prop.withValueDeserializer(deser);
} else { // may need contextual version
JsonDeserializer<Object> deser = prop.getValueDeserializer();
/* Important! This is the only place where actually handle "primary"
* property deserializers -- call is different from other places.
*/
JsonDeserializer<?> cd = ctxt.handlePrimaryContextualization(deser, prop);
if (cd != deser) {
prop = prop.withValueDeserializer(cd);
}
}
// [JACKSON-235]: need to link managed references with matching back references
prop = _resolveManagedReferenceProperty(ctxt, prop);
// issue #351: need to wrap properties that require object id resolution.
if (!(prop instanceof ManagedReferenceProperty)) {
prop = _resolvedObjectIdProperty(ctxt, prop
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
}
AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator();
// Need to create a temporary property to allow contextual deserializers:
BeanProperty.Std property = new BeanProperty.Std(TEMP_PROPERTY_NAME,
delegateType, null, _classAnnotations, delegateCreator,
PropertyMetadata.STD_OPTIONAL);
_delegateDeserializer = findDeserializer(ctxt, delegateType, property);
}
if (extTypes != null) {
_externalTypeIdHandler = extTypes.build();
// we consider this non-standard, to offline handling
_nonStandardCreation = true;
}
_unwrappedPropertyHandler = unwrapped;
if (unwrapped != null) { // we consider this non-standard, to offline handling
_nonStandardCreation = true;
}
// may need to disable vanilla processing, if unwrapped handling was enabled...
_vanillaProcessing = _vanillaProcessing && !_nonStandardCreation;
}
/**
* Helper method that can be used to see if specified property is annotated
* to indicate use of a converter for property value (in case of container types,
* it is container type itself, not key or content type).
*
* @since 2.2
*/
protected JsonDeserializer<Object> findConvertingDeserializer(DeserializationContext ctxt,
SettableBeanProperty prop)
throws JsonMappingException
{
final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
if (intr != null) {
Object convDef = intr.findDeserializationConverter(prop.getMember());
if (convDef != null) {
Converter<Object,Object> conv = ctxt.converterInstance(prop.getMember(), convDef);
JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
JsonDeserializer<?> ser = ctxt.findContextualValueDeserializer(delegateType, prop);
return new StdDelegatingDeserializer<Object>(conv, delegateType, ser);
}
}
return null;
}
/**
* Although most of post-processing is done in resolve(), we only get
* access to referring property's annotations here; and this is needed
* to support per-property ObjectIds.
* We will also consider Shape transformations (read from Array) at this
* point, since it may come from either Class definition or property.
*/
@Override
public Json
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Deserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
ObjectIdReader oir = _objectIdReader;
// First: may have an override for Object Id:
final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
final AnnotatedMember accessor = (property == null || intr == null)
? null : property.getMember();
if (accessor != null && intr != null) {
ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
if (objectIdInfo != null) { // some code duplication here as well (from BeanDeserializerFactory)
// 2.1: allow modifications by "id ref" annotations as well:
objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo);
Class<?> implClass = objectIdInfo.getGeneratorType();
// Property-based generator is trickier
JavaType idType;
SettableBeanProperty idProp;
ObjectIdGenerator<?> idGen;
ObjectIdResolver resolver = ctxt.objectIdResolverInstance(accessor, objectIdInfo);
if (implClass == ObjectIdGenerators.PropertyGenerator.class) {
PropertyName propName = objectIdInfo.getPropertyName();
idProp = findProperty(propName);
if (idProp == null) {
throw new IllegalArgumentException("Invalid Object Id definition for "
+handledType().getName()+": can not find property with name '"+propName+"'");
}
idType = idProp.getType();
idGen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope());
} else { // other types need to be simpler
JavaType type = ctxt.constructType(implClass);
idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
idProp = null;
idGen = ctxt.objectIdGeneratorInstance(accessor, objectIdInfo);
}
JsonDeserializer<?> deser = ctxt.findRootValueDeserializer(idType);
oir = ObjectIdReader.construct(idType, objectIdInfo.getPropertyName(),
idGen, deser, idProp, resolver);
}
}
// either way, need to resolve serializer:
BeanDeserializerBase contextual = this;
if (oir != null && oir != _objectIdReader) {
contextual = contextual.withObjectIdReader(oir);
}
//
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(jp, ctxt));
}
if (_propertyBasedCreator != null) {
return _deserializeUsingPropertyBased(jp, ctxt);
}
// should only occur for abstract types...
if (_beanType.isAbstract()) {
throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_beanType
+" (need to add/enable type information?)");
}
throw JsonMappingException.from(jp, "No suitable constructor found for type "
+_beanType+": can not instantiate from JSON object (need to add/enable type information?)");
}
protected abstract Object _deserializeUsingPropertyBased(final JsonParser jp,
final DeserializationContext ctxt)
throws IOException, JsonProcessingException;
@SuppressWarnings("incomplete-switch")
public Object deserializeFromNumber(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// First things first: id Object Id is used, most likely that's it
if (_objectIdReader != null) {
return deserializeFromObjectId(jp, ctxt);
}
switch (jp.getNumberType()) {
case INT:
if (_delegateDeserializer != null) {
if (!_valueInstantiator.canCreateFromInt()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
return _valueInstantiator.createFromInt(ctxt, jp.getIntValue());
case LONG:
if (_delegateDeserializer != null) {
if (!_valueInstantiator.canCreateFromInt()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
return _valueInstantiator.createFromLong(ctxt, jp.getLongValue());
}
// actually, could also be BigInteger, so:
if (_delegateDeserializer != null) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
throw ctxt.instantiationException(getBeanClass
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
boolean value = (jp.getCurrentToken() == JsonToken.VALUE_TRUE);
return _valueInstantiator.createFromBoolean(ctxt, value);
}
public Object deserializeFromArray(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_delegateDeserializer != null) {
try {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
}
} else if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final Object value = deserialize(jp, ctxt);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
}
return value;
}
throw ctxt.mappingException(getBeanClass());
}
/*
/**********************************************************
/* Overridable helper methods
/**********************************************************
*/
protected void injectValues(DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
for (ValueInjector injector : _injectables) {
injector.inject(ctxt, bean);
}
}
/**
* Method called to handle set of one or more unknown properties,
* stored in their entirety in given {@link TokenBuffer}
* (as field entries, name and value).
*/
@SuppressWarnings("resource")
protected Object handleUnknownProperties(DeserializationContext ctxt,
Object bean, TokenBuffer unknownTokens)
throws IOException, JsonProcessingException
{
// First: add closing END_OBJECT as marker
unknownTokens.writeEndObject();
// note: buffer does NOT have starting START_OBJECT
JsonParser bufferParser = unknownTokens.asParser();
while (buffer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Parser.nextToken() != JsonToken.END_OBJECT) {
String propName = bufferParser.getCurrentName();
// Unknown: let's call handler method
bufferParser.nextToken();
handleUnknownProperty(bufferParser, ctxt, bean, propName);
}
return bean;
}
/**
* Helper method called for an unknown property, when using "vanilla"
* processing.
*/
protected void handleUnknownVanilla(JsonParser jp, DeserializationContext ctxt,
Object bean, String propName)
throws IOException, JsonProcessingException
{
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
} else if (_anySetter != null) {
try {
// should we consider return type of any setter?
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
} else {
// Unknown: let's call handler method
handleUnknownProperty(jp, ctxt, bean, propName);
}
}
/**
* Method called when a JSON property is encountered that has not matching
* setter, any-setter or field, and thus can not be assigned.
*/
@Override
protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt,
Object beanOrClass, String propName)
throws IOException, JsonProcessingException
{
if (_ignoreAllUnknown) {
jp.skipChildren();
return;
}
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, beanOrClass, propName);
}
// Otherwise use default handling (call handler(s); if not
// handled, throw exception or skip depending on settings)
super.handleUnknownProperty(jp, ctxt, beanOrClass, propName);
}
/**
* Method called when an explicitly ignored property (one specified with a
* name to match, either by property annotation or class annotation) is encountered.
*
* @since 2.3
*/
protected void handleIgnoredProperty(JsonParser jp, DeserializationContext ctxt,
Object beanOrClass, String propName)
throws IOException, JsonProcessingException
{
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Buffer unknownTokens)
throws IOException, JsonProcessingException
{
JsonDeserializer<Object> subDeser;
// First: maybe we have already created sub-type deserializer?
synchronized (this) {
subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass()));
}
if (subDeser != null) {
return subDeser;
}
// If not, maybe we can locate one. First, need provider
JavaType type = ctxt.constructType(bean.getClass());
/* 30-Jan-2012, tatu: Ideally we would be passing referring
* property; which in theory we could keep track of via
* ResolvableDeserializer (if we absolutely must...).
* But for now, let's not bother.
*/
// subDeser = ctxt.findValueDeserializer(type, _property);
subDeser = ctxt.findRootValueDeserializer(type);
// Also, need to cache it
if (subDeser != null) {
synchronized (this) {
if (_subDeserializers == null) {
_subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();;
}
_subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
}
}
return subDeser;
}
/*
/**********************************************************
/* Helper methods for error reporting
/**********************************************************
*/
/**
* Method that will modify caught exception (passed in as argument)
* as necessary to include reference information, and to ensure it
* is a subtype of {@link IOException}, or an unchecked exception.
*<p>
* Rules for wrapping and unwrapping are bit complicated; essentially:
*<ul>
* <li>Errors are to be passed as is (if uncovered via unwrapping)
* <li>"Plain" IOExceptions (ones that are not of type
* {@link JsonMappingException} are to be passed as is
*</ul>
*/
public void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
throws IOException
{
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>), bean, fieldName);
}
@Deprecated // since 2.4, not used by core Jackson; only relevant for arrays/Collections
public void wrapAndThrow(Throwable t, Object bean, int index, DeserializationContext ctxt) throws IOException {
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, index);
}
private Throwable throwOrReturnThrowable(Throwable t, DeserializationContext ctxt)
throws IOException
{
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that
* often gets hidden within an InvocationTargetException...
*/
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
// Ditto for IOExceptions; except we may want to wrap JSON exceptions
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonProcessingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
return t;
}
protected void wrapInstantiationProblem(Throwable t, DeserializationContext ctxt)
throws IOException
{
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
if (t instanceof IOException) {
// Since we have no more information to add, let's not actually wrap..
throw (IOException) t;
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>_JAVAX_XML)
|| hasSupertypeStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
factoryName = SERIALIZERS_FOR_JAVAX_XML;
} else if (doesImplement(rawType, CLASS_NAME_DOM_NODE)) {
return (JsonSerializer<?>) instantiate(SERIALIZER_FOR_DOM_NODE);
} else {
return null;
}
Object ob = instantiate(factoryName);
if (ob == null) { // could warn, if we had logging system (j.u.l?)
return null;
}
return ((Serializers) ob).findSerializer(config, type, beanDesc);
}
public JsonDeserializer<?> findDeserializer(JavaType type, DeserializationConfig config,
BeanDescription beanDesc)
throws JsonMappingException
{
Class<?> rawType = type.getRawClass();
String className = rawType.getName();
String factoryName;
if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML)
|| hasSupertypeStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
factoryName = DESERIALIZERS_FOR_JAVAX_XML;
} else if (doesImplement(rawType, CLASS_NAME_DOM_DOCUMENT)) {
return (JsonDeserializer<?>) instantiate(DESERIALIZER_FOR_DOM_DOCUMENT);
} else if (doesImplement(rawType, CLASS_NAME_DOM_NODE)) {
return (JsonDeserializer<?>) instantiate(DESERIALIZER_FOR_DOM_NODE);
} else {
return null;
}
Object ob = instantiate(factoryName);
if (ob == null) { // could warn, if we had logging system (j.u.l?)
return null;
}
return ((Deserializers) ob).findBeanDeserializer(type, config, beanDesc);
}
/*
/**********************************************************
/* Internal helper methods
/**********************************************************
*/
private Object instantiate(String className)
{
try {
return Class.forName(className).newInstance();
} catch (LinkageError e) { }
// too many different kinds to enumerate here:
catch (Exception e) { }
return null;
}
private boolean doesImplement(Class<?> actualType, String classNameToImplement)
{
for (
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> }
/*
/**********************************************************
/* Access to Object Id aspects
/**********************************************************
*/
/**
* Method called to find the Object Id for given POJO, if one
* has been generated. Will always return a non-null Object;
* contents vary depending on whether an Object Id already
* exists or not.
*/
public abstract WritableObjectId findObjectId(Object forPojo,
ObjectIdGenerator<?> generatorType);
/*
/**********************************************************
/* General serializer locating functionality
/**********************************************************
*/
/**
* Method called to get hold of a serializer for a value of given type;
* or if no such serializer can be found, a default handler (which
* may do a best-effort generic serialization or just simply
* throw an exception when invoked).
*<p>
* Note: this method is only called for non-null values; not for keys
* or null values. For these, check out other accessor methods.
*<p>
* Note that starting with version 1.5, serializers should also be type-aware
* if they handle polymorphic types. That means that it may be necessary
* to also use a {@link TypeSerializer} based on declared (static) type
* being serializer (whereas actual data may be serialized using dynamic
* type)
*
* @throws JsonMappingException if there are fatal problems with
* accessing suitable serializer; including that of not
* finding any serializer
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findValueSerializer(Class<?> valueType,
BeanProperty property)
throws JsonMappingException
{
// Fast lookup from local lookup thingy works?
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
// If not, maybe shared map already has it?
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
// ... possibly as fully typed?
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
if (ser == null) {
// If neither, must create
ser = _createAndCacheUntypedSerializer(valueType);
// Not found? Must use the unknown type serializer
/* Couldn't create? Need to return the fallback serializer, which
* most likely will report
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> an error: but one question is whether
* we should cache it?
*/
if (ser == null) {
ser = getUnknownTypeSerializer(valueType);
// Should this be added to lookups?
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
}
// at this point, resolution has occured, but not contextualization
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
/**
* Similar to {@link #findValueSerializer(Class,BeanProperty)}, but takes
* full generics-aware type instead of raw class.
* This is necessary for accurate handling of external type information,
* to handle polymorphic types.
*
* @param property When creating secondary serializers, property for which
* serializer is needed: annotations of the property (or bean that contains it)
* may be checked to create contextual serializers.
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProperty property)
throws JsonMappingException
{
// Fast lookup from local lookup thingy works?
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
// If not, maybe shared map already has it?
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
// If neither, must create
ser = _createAndCacheUntypedSerializer(valueType);
// Not found? Must use the unknown type serializer
/* Couldn't create? Need to return the fallback serializer, which
* most likely will report an error: but one question is whether
* we should cache it?
*/
if (ser == null) {
ser = getUnknownTypeSerializer(valueType.getRawClass());
// Should this be added to lookups?
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
/**
* Similar to {@link #findValueSerializer(JavaType, BeanProperty)}, but
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> used
* when finding "primary" property value serializer (one directly handling
* value of the property). Difference has to do with contextual resolution,
* and method(s) called: this method should only be called when caller is
* certain that this is the primary property value serializer.
*
* @param property Property that is being handled; will never be null, and its
* type has to match <code>valueType</code> parameter.
*
* @since 2.3
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findPrimaryPropertySerializer(JavaType valueType, BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType.getRawClass());
// Should this be added to lookups?
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
return (JsonSerializer<Object>) handlePrimaryContextualization(ser, property);
}
/**
* @since 2.3
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findPrimaryPropertySerializer(Class<?> valueType,
BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType);
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
}
return (JsonSerializer<Object>) handlePrimaryContextualization(ser,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> property);
}
/**
* Method called to locate regular serializer, matching type serializer,
* and if both found, wrap them in a serializer that calls both in correct
* sequence. This method is currently only used for root-level serializer
* handling to allow for simpler caching. A call can always be replaced
* by equivalent calls to access serializer and type serializer separately.
*
* @param valueType Type for purpose of locating a serializer; usually dynamic
* runtime type, but can also be static declared type, depending on configuration
* @param cache Whether resulting value serializer should be cached or not; this is just
* a hint
* @param property When creating secondary serializers, property for which
* serializer is needed: annotations of the property (or bean that contains it)
* may be checked to create contextual serializers.
*/
public JsonSerializer<Object> findTypedValueSerializer(Class<?> valueType,
boolean cache, BeanProperty property)
throws JsonMappingException
{
// Two-phase lookups; local non-shared cache, then shared:
JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// If not, maybe shared map already has it?
ser = _serializerCache.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// Well, let's just compose from pieces:
ser = findValueSerializer(valueType, property);
TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config,
_config.constructType(valueType));
if (typeSer != null) {
typeSer = typeSer.forProperty(property);
ser = new TypeWrappedSerializer(typeSer, ser);
}
if (cache) {
_serializerCache.addTypedSerializer(valueType, ser);
}
return ser;
}
/**
* Method called to locate regular serializer, matching type serializer,
* and if both found, wrap them in a serializer that calls both in correct
* sequence. This method is currently only used for root-level serializer
* handling to allow for simpler caching. A call can always be replaced
* by equivalent calls to access serializer and type serializer separately.
*
* @param valueType Declared type of value being serialized (which may not
*
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> be actual runtime type); used for finding both value serializer and
* type serializer to use for adding polymorphic type (if any)
* @param cache Whether resulting value serializer should be cached or not; this is just
* a hint
* @param property When creating secondary serializers, property for which
* serializer is needed: annotations of the property (or bean that contains it)
* may be checked to create contextual serializers.
*/
public JsonSerializer<Object> findTypedValueSerializer(JavaType valueType, boolean cache,
BeanProperty property)
throws JsonMappingException
{
// Two-phase lookups; local non-shared cache, then shared:
JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// If not, maybe shared map already has it?
ser = _serializerCache.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// Well, let's just compose from pieces:
ser = findValueSerializer(valueType, property);
TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, valueType);
if (typeSer != null) {
typeSer = typeSer.forProperty(property);
ser = new TypeWrappedSerializer(typeSer, ser);
}
if (cache) {
_serializerCache.addTypedSerializer(valueType, ser);
}
return ser;
}
/**
* Method called to get the serializer to use for serializing
* non-null Map keys. Separation from regular
* {@link #findValueSerializer} method is because actual write
* method must be different (@link JsonGenerator#writeFieldName};
* but also since behavior for some key types may differ.
*<p>
* Note that the serializer itself can be called with instances
* of any Java object, but not nulls.
*/
public JsonSerializer<Object> findKeySerializer(JavaType keyType,
BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _serializerFactory.createKeySerializer(_config, keyType, _keySerializer);
// 25-Feb-2011, tatu: As per [JACKSON-519], need to ensure contextuality works here, too
return _
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>handleContextualResolvable(ser, property);
}
/*
/********************************************************
/* Accessors for specialized serializers
/********************************************************
*/
/**
* @since 2.0
*/
public JsonSerializer<Object> getDefaultNullKeySerializer() {
return _nullKeySerializer;
}
/**
* @since 2.0
*/
public JsonSerializer<Object> getDefaultNullValueSerializer() {
return _nullValueSerializer;
}
/**
* Method called to get the serializer to use for serializing
* Map keys that are nulls: this is needed since JSON does not allow
* any non-String value as key, including null.
*<p>
* Typically, returned serializer
* will either throw an exception, or use an empty String; but
* other behaviors are possible.
*/
/**
* Method called to find a serializer to use for null values for given
* declared type. Note that type is completely based on declared type,
* since nulls in Java have no type and thus runtime type can not be
* determined.
*
* @since 2.0
*/
public JsonSerializer<Object> findNullKeySerializer(JavaType serializationType,
BeanProperty property)
throws JsonMappingException
{
return _nullKeySerializer;
}
/**
* Method called to get the serializer to use for serializing null
* values for specified property.
*<p>
* Default implementation simply calls {@link #getDefaultNullValueSerializer()};
* can be overridden to add custom null serialization for properties
* of certain type or name. This gives method full granularity to basically
* override null handling for any specific property or class of properties.
*
* @since 2.0
*/
public JsonSerializer<Object> findNullValueSerializer(BeanProperty property)
throws JsonMappingException {
return _nullValueSerializer;
}
/**
* Method called to get the serializer to use if provider
* can not determine an actual type-specific serializer
* to use; typically when none of {@link SerializerFactory}
* instances are able to construct a serializer.
*<p>
* Typically, returned serializer will throw an exception,
* although alternatively {@link com.fasterxml.jackson.databind.ser.std.ToStringSerializer}
* could be returned as well.
*
* @param unknownType Type for which no serializer is found
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
*/
public JsonSerializer<Object> getUnknownTypeSerializer(Class<?> unknownType) {
return _unknownTypeSerializer;
}
/*
/**********************************************************
/* Methods for creating instances based on annotations
/**********************************************************
*/
/**
* Method that can be called to construct and configure serializer instance,
* either given a {@link Class} to instantiate (with default constructor),
* or an uninitialized serializer instance.
* Either way, serialize will be properly resolved
* (via {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer}) and/or contextualized
* (via {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}) as necessary.
*
* @param annotated Annotated entity that contained definition
* @param serDef Serializer definition: either an instance or class
*/
public abstract JsonSerializer<Object> serializerInstance(Annotated annotated,
Object serDef)
throws JsonMappingException;
/*
/**********************************************************
/* Support for contextualization
/**********************************************************
*/
/**
* @deprecated Since 2.3 (and to be removed from 2.4); use
* {@link #handlePrimaryContextualization} or {@link #handleSecondaryContextualization}
* instead
*/
@Deprecated
public JsonSerializer<?> handleContextualization(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
return handleSecondaryContextualization(ser, property);
}
/**
* Method called for primary property serializers (ones
* directly created to serialize values of a POJO property),
* to handle details of resolving
* {@link ContextualSerializer} with given property context.
*
* @param property Property for which the given primary serializer is used; never null.
*
* @since 2.3
*/
public JsonSerializer<?> handlePrimaryContextualization(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
if (ser != null) {
if (ser instanceof ContextualSerializer) {
ser = ((ContextualSerializer) ser).createContextual(this, property);
}
}
return ser;
}
/**
* Method called for secondary property serializers (ones
* NOT directly created to serialize values of a POJO property
* but instead created as a dependant serializer -- such as value serializers
* for structured
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> types, or serializers for root values)
* to handle details of resolving
* {@link ContextualDeserializer} with given property context.
* Given that these serializers are not directly related to given property
* (or, in case of root value property, to any property), annotations
* accessible may or may not be relevant.
*
* @param property Property for which serializer is used, if any; null
* when deserializing root values
*
* @since 2.3
*/
public JsonSerializer<?> handleSecondaryContextualization(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
if (ser != null) {
if (ser instanceof ContextualSerializer) {
ser = ((ContextualSerializer) ser).createContextual(this, property);
}
}
return ser;
}
/*
/********************************************************
/* Convenience methods
/********************************************************
*/
/**
* Convenience method that will serialize given value (which can be
* null) using standard serializer locating functionality. It can
* be called for all values including field and Map values, but usually
* field values are best handled calling
* {@link #defaultSerializeField} instead.
*/
public final void defaultSerializeValue(Object value, JsonGenerator jgen)
throws IOException, JsonProcessingException
{
if (value == null) {
if (_stdNullValueSerializer) { // minor perf optimization
jgen.writeNull();
} else {
_nullValueSerializer.serialize(null, jgen, this);
}
} else {
Class<?> cls = value.getClass();
findTypedValueSerializer(cls, true, null).serialize(value, jgen, this);
}
}
/**
* Convenience method that will serialize given field with specified
* value. Value may be null. Serializer is done using the usual
* null) using standard serializer locating functionality.
*/
public final void defaultSerializeField(String fieldName, Object value, JsonGenerator jgen)
throws IOException, JsonProcessingException
{
jgen.writeFieldName(fieldName);
if (value == null) {
/* Note: can't easily check for suppression at this point
* any more; caller must check it.
*/
if (_stdNullValueSerializer) { // minor perf optimization
jgen.writeNull();
} else {
_nullValueSerializer.serialize(
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>valueOf(timestamp));
} else {
jgen.writeFieldName(_dateFormat().format(new Date(timestamp)));
}
}
/**
* Method that will handle serialization of Dates used as {@link java.util.Map} keys,
* based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS}
* value (and if using textual representation, configured date format)
*/
public void defaultSerializeDateKey(Date date, JsonGenerator jgen)
throws IOException, JsonProcessingException
{
if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) {
jgen.writeFieldName(String.valueOf(date.getTime()));
} else {
jgen.writeFieldName(_dateFormat().format(date));
}
}
public final void defaultSerializeNull(JsonGenerator jgen)
throws IOException, JsonProcessingException
{
if (_stdNullValueSerializer) { // minor perf optimization
jgen.writeNull();
} else {
_nullValueSerializer.serialize(null, jgen, this);
}
}
/*
/********************************************************
/* Helper methods
/********************************************************
*/
protected void _reportIncompatibleRootType(Object value, JavaType rootType)
throws IOException, JsonProcessingException
{
/* 07-Jan-2010, tatu: As per [JACKSON-456] better handle distinction between wrapper types,
* primitives
*/
if (rootType.isPrimitive()) {
Class<?> wrapperType = ClassUtil.wrapperType(rootType.getRawClass());
// If it's just difference between wrapper, primitive, let it slide
if (wrapperType.isAssignableFrom(value.getClass())) {
return;
}
}
throw new JsonMappingException("Incompatible types: declared root type ("+rootType+") vs "
+value.getClass().getName());
}
/**
* Method that will try to find a serializer, either from cache
* or by constructing one; but will not return an "unknown" serializer
* if this can not be done but rather returns null.
*
* @return Serializer if one can be found, null if not.
*/
protected JsonSerializer<Object> _findExplicitUntypedSerializer(Class<?> runtimeType)
throws JsonMappingException
{
// Fast lookup from local lookup
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> thingy works?
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(runtimeType);
if (ser != null) {
return ser;
}
// If not, maybe shared map already has it?
ser = _serializerCache.untypedValueSerializer(runtimeType);
if (ser != null) {
return ser;
}
return _createAndCacheUntypedSerializer(runtimeType);
}
/*
/**********************************************************
/* Low-level methods for actually constructing and initializing
/* serializers
/**********************************************************
*/
/**
* Method that will try to construct a value serializer; and if
* one is successfully created, cache it for reuse.
*/
protected JsonSerializer<Object> _createAndCacheUntypedSerializer(Class<?> type)
throws JsonMappingException
{
JsonSerializer<Object> ser;
try {
ser = _createUntypedSerializer(_config.constructType(type));
} catch (IllegalArgumentException iae) {
/* We better only expose checked exceptions, since those
* are what caller is expected to handle
*/
throw new JsonMappingException(iae.getMessage(), null, iae);
}
if (ser != null) {
_serializerCache.addAndResolveNonTypedSerializer(type, ser, this);
}
return ser;
}
protected JsonSerializer<Object> _createAndCacheUntypedSerializer(JavaType type)
throws JsonMappingException
{
JsonSerializer<Object> ser;
try {
ser = _createUntypedSerializer(type);
} catch (IllegalArgumentException iae) {
/* We better only expose checked exceptions, since those
* are what caller is expected to handle
*/
throw new JsonMappingException(iae.getMessage(), null, iae);
}
if (ser != null) {
_serializerCache.addAndResolveNonTypedSerializer(type, ser, this);
}
return ser;
}
/**
* @since 2.1
*/
protected JsonSerializer<Object> _createUntypedSerializer(JavaType type)
throws JsonMappingException
{
// 17-Feb-2013, tatu: Used to call deprecated method (that passed property)
return (JsonSerializer<Object>)_serializerFactory.createSerializer(this, type);
}
/**
* Helper method called to resolve and contextual
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>ize given
* serializer, if and as necessary.
*/
@SuppressWarnings("unchecked")
protected JsonSerializer<Object> _handleContextualResolvable(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
if (ser instanceof ResolvableSerializer) {
((ResolvableSerializer) ser).resolve(this);
}
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
@SuppressWarnings("unchecked")
protected JsonSerializer<Object> _handleResolvable(JsonSerializer<?> ser)
throws JsonMappingException
{
if (ser instanceof ResolvableSerializer) {
((ResolvableSerializer) ser).resolve(this);
}
return (JsonSerializer<Object>) ser;
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected final DateFormat _dateFormat()
{
if (_dateFormat != null) {
return _dateFormat;
}
/* 24-Feb-2012, tatu: At this point, all timezone configuration
* should have occured, with respect to default dateformat
* and timezone configuration. But we still better clone
* an instance as formatters may be stateful.
*/
DateFormat df = _config.getDateFormat();
_dateFormat = df = (DateFormat) df.clone();
return df;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> || ignorable.length == 0) ?
null : ArrayBuilders.arrayToSet(ignorable);
}
/*
/**********************************************************
/* Validation, post-processing (ResolvableDeserializer)
/**********************************************************
*/
@Override
public void resolve(DeserializationContext ctxt) throws JsonMappingException
{
// May need to resolve types for delegate- and/or property-based creators:
if (_valueInstantiator.canCreateUsingDelegate()) {
JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
if (delegateType == null) {
throw new IllegalArgumentException("Invalid delegate-creator definition for "+_mapType
+": value instantiator ("+_valueInstantiator.getClass().getName()
+") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'");
}
/* Theoretically should be able to get CreatorProperty for delegate
* parameter to pass; but things get tricky because DelegateCreator
* may contain injectable values. So, for now, let's pass nothing.
*/
_delegateDeserializer = findDeserializer(ctxt, delegateType, null);
}
if (_valueInstantiator.canCreateFromObjectWith()) {
SettableBeanProperty[] creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
_propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps);
}
_standardStringKey = _isStdKeyDeser(_mapType, _keyDeserializer);
}
/**
* Method called to finalize setup of this deserializer,
* when it is known for which property deserializer is needed for.
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
KeyDeserializer kd = _keyDeserializer;
if (kd == null) {
kd = ctxt.findKeyDeserializer(_mapType.getKeyType(), property);
} else {
if (kd instanceof ContextualKeyDeserializer) {
kd = ((ContextualKeyDeserializer) kd).createContextual(ctxt, property);
}
}
JsonDeserializer<?> vd = _valueDeserializer;
// #125: May have a content converter
vd = findConvertingContentDeserializer(ctxt, property, vd);
if (vd == null) {
vd
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> prop = creator.findCreatorProperty(propName);
if (prop != null) {
// Last property to set?
Object value = prop.deserialize(jp, ctxt);
if (buffer.assignParameter(prop.getCreatorIndex(), value)) {
jp.nextToken();
Map<Object,Object> result;
try {
result = (Map<Object,Object>)creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _mapType.getRawClass());
return null;
}
_readAndBind(jp, ctxt, result);
return result;
}
continue;
}
// other property? needs buffering
String fieldName = jp.getCurrentName();
Object key = _keyDeserializer.deserializeKey(fieldName, ctxt);
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
buffer.bufferMapProperty(key, value);
}
// end of JSON object?
// if so, can just construct and leave...
try {
return (Map<Object,Object>)creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _mapType.getRawClass());
return null;
}
}
// note: copied from BeanDeserializer; should try to share somehow...
protected void wrapAndThrow(Throwable t, Object ref)
throws IOException
{
// to handle StackOverflow:
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// ... except for mapping exceptions
if (t instanceof IOException && !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
throw JsonMappingException.wrapWithPath(t, ref, null);
}
private void handleUnresolvedReference(JsonParser jp, MapReferringAccumulator accumulator, Object key,
UnresolvedForwardReference reference)
throws JsonMappingException
{
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
if (accumulator == null) {
throw JsonMappingException.from(jp, "Unresolved forward reference but no identity info.", reference);
}
Referring referring = accumulator.handleUnresolvedReference(reference, key);
reference.getRoid().appendReferring(referring);
}
private final static class MapReferringAccumulator {
private final Class<?> _valueType;
private Map<Object,Object> _result;
/**
* A list of {@link MapReferring} to maintain ordering.
*/
private List<MapReferring> _accumulator = new ArrayList<MapReferring>();
public MapReferringAccumulator(Class<?> valueType, Map<Object, Object> result) {
_valueType = valueType;
_result = result;
}
public void put(Object key, Object value)
{
if (_accumulator.isEmpty()) {
_result.put(key, value);
} else {
MapReferring ref = _accumulator.get(_accumulator.size() - 1);
ref.next.put(key, value);
}
}
public Referring handleUnresolvedReference(UnresolvedForwardReference reference, Object key)
{
MapReferring id = new MapReferring(this, reference, _valueType, key);
_accumulator.add(id);
return id;
}
public void resolveForwardReference(Object id, Object value) throws IOException
{
Iterator<MapReferring> iterator = _accumulator.iterator();
// Resolve ordering after resolution of an id. This means either:
// 1- adding to the result map in case of the first unresolved id.
// 2- merge the content of the resolved id with its previous unresolved id.
Map<Object,Object> previous = _result;
while (iterator.hasNext()) {
MapReferring ref = iterator.next();
if (ref.hasId(id)) {
iterator.remove();
previous.put(ref.key, value);
previous.putAll(ref.next);
return;
}
previous = ref.next;
}
throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id
+ "] that wasn't previously seen as unresolved.");
}
}
/**
* Helper class to maintain processing order of value. The resolved
* object associated with {@link #_
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.impl;
import java.io.IOException;
import java.util.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase;
/**
* Efficient implement for serializing {@link List}s that contains Strings and are random-accessible.
* The only complexity is due to possibility that serializer for {@link String}
* may be overridde; because of this, logic is needed to ensure that the default
* serializer is in use to use fastest mode, or if not, to defer to custom
* String serializer.
*/
@JacksonStdImpl
public final class IndexedStringListSerializer
extends StaticListSerializerBase<List<String>>
implements ContextualSerializer
{
public final static IndexedStringListSerializer instance = new IndexedStringListSerializer();
protected final JsonSerializer<String> _serializer;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
protected IndexedStringListSerializer() { this(null); }
@SuppressWarnings("unchecked")
public IndexedStringListSerializer(JsonSerializer<?> ser) {
super(List.class);
_serializer = (JsonSerializer<String>) ser;
}
@Override protected JsonNode contentSchema() { return createSchemaNode("string", true); }
@Override
protected void acceptContentVisitor(JsonArrayFormatVisitor visitor) throws JsonMappingException {
visitor.itemsFormat(JsonFormatTypes.STRING);
}
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException
{
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
*
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Custom(value, jgen, provider, 1);
}
}
@Override
public void serializeWithType(List<String> value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer) throws IOException
{
final int len = value.size();
typeSer.writeTypePrefixForArray(value, jgen);
if (_serializer == null) {
serializeContents(value, jgen, provider, len);
} else {
serializeUsingCustom(value, jgen, provider, len);
}
typeSer.writeTypeSuffixForArray(value, jgen);
}
private final void serializeContents(List<String> value, JsonGenerator jgen, SerializerProvider provider,
int len) throws IOException
{
int i = 0;
try {
for (; i < len; ++i) {
String str = value.get(i);
if (str == null) {
provider.defaultSerializeNull(jgen);
} else {
jgen.writeString(str);
}
}
} catch (Exception e) {
wrapAndThrow(provider, e, value, i);
}
}
private final void serializeUsingCustom(List<String> value, JsonGenerator jgen, SerializerProvider provider,
int len) throws IOException
{
int i = 0;
try {
final JsonSerializer<String> ser = _serializer;
for (i = 0; i < len; ++i) {
String str = value.get(i);
if (str == null) {
provider.defaultSerializeNull(jgen);
} else {
ser.serialize(str, jgen, provider);
}
}
} catch (Exception e) {
wrapAndThrow(provider, e, value, i);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.impl;
import java.io.IOException;
import java.util.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase;
/**
* Efficient implement for serializing {@link Collection}s that contain Strings.
* The only complexity is due to possibility that serializer for {@link String}
* may be overridde; because of this, logic is needed to ensure that the default
* serializer is in use to use fastest mode, or if not, to defer to custom
* String serializer.
*/
@JacksonStdImpl
public class StringCollectionSerializer
extends StaticListSerializerBase<Collection<String>>
implements ContextualSerializer
{
public final static StringCollectionSerializer instance = new StringCollectionSerializer();
protected final JsonSerializer<String> _serializer;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
protected StringCollectionSerializer() {
this(null);
}
@SuppressWarnings("unchecked")
protected StringCollectionSerializer(JsonSerializer<?> ser)
{
super(Collection.class);
_serializer = (JsonSerializer<String>) ser;
}
@Override protected JsonNode contentSchema() {
return createSchemaNode("string", true);
}
@Override
protected void acceptContentVisitor(JsonArrayFormatVisitor visitor)
throws JsonMappingException
{
visitor.itemsFormat(JsonFormatTypes.STRING);
}
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
* checking here
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, provider);
}
}
@Override
public void serializeWithType(Collection<String> value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonGenerationException
{
typeSer.writeTypePrefixForArray(value, jgen);
if (_serializer == null) {
serializeContents(value, jgen, provider);
} else {
serializeUsingCustom(value, jgen, provider);
}
typeSer.writeTypeSuffixForArray(value, jgen);
}
private final void serializeContents(Collection<String> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
if (_serializer != null) {
serializeUsingCustom(value, jgen, provider);
return;
}
int i = 0;
for (String str : value) {
try {
if (str == null) {
provider.defaultSerializeNull(jgen);
} else {
jgen.writeString(str);
}
++i;
} catch (Exception e) {
wrapAndThrow(provider, e, value, i);
}
}
}
private void serializeUsingCustom(Collection<String> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
final JsonSerializer<String> ser = _serializer;
int i = 0;
for (String str : value) {
try {
if (str == null) {
provider.defaultSerializeNull(jgen);
} else {
ser.serialize(str, jgen, provider);
}
} catch (Exception e) {
wrapAndThrow(provider, e, value, i);
}
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>) {
return new MethodProperty(this, deser);
}
/*
/**********************************************************
/* BeanProperty impl
/**********************************************************
*/
@Override
public <A extends Annotation> A getAnnotation(Class<A> acls) {
return _annotated.getAnnotation(acls);
}
@Override public AnnotatedMember getMember() { return _annotated; }
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
set(instance, deserialize(jp, ctxt));
}
@Override
public Object deserializeSetAndReturn(JsonParser jp,
DeserializationContext ctxt, Object instance) throws IOException
{
return setAndReturn(instance, deserialize(jp, ctxt));
}
@Override
public final void set(Object instance, Object value) throws IOException
{
try {
_setter.invoke(instance, value);
} catch (Exception e) {
_throwAsIOE(e, value);
}
}
@Override
public Object setAndReturn(Object instance, Object value) throws IOException
{
try {
Object result = _setter.invoke(instance, value);
return (result == null) ? instance : result;
} catch (Exception e) {
_throwAsIOE(e, value);
return null;
}
}
/*
/**********************************************************
/* JDK serialization handling
/**********************************************************
*/
Object readResolve() {
return new MethodProperty(this, _annotated.getAnnotated());
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> _buildMethod = src._buildMethod;
}
protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) {
super(src, unwrapper);
_buildMethod = src._buildMethod;
}
public BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir) {
super(src, oir);
_buildMethod = src._buildMethod;
}
public BuilderBasedDeserializer(BuilderBasedDeserializer src, HashSet<String> ignorableProps) {
super(src, ignorableProps);
_buildMethod = src._buildMethod;
}
@Override
public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
{
/* main thing really is to just enforce ignoring of unknown
* properties; since there may be multiple unwrapped values
* and properties for all may be interleaved...
*/
return new BuilderBasedDeserializer(this, unwrapper);
}
@Override
public BuilderBasedDeserializer withObjectIdReader(ObjectIdReader oir) {
return new BuilderBasedDeserializer(this, oir);
}
@Override
public BuilderBasedDeserializer withIgnorableProperties(HashSet<String> ignorableProps) {
return new BuilderBasedDeserializer(this, ignorableProps);
}
@Override
protected BeanAsArrayBuilderDeserializer asArrayDeserializer() {
SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
return new BeanAsArrayBuilderDeserializer(this, props, _buildMethod);
}
/*
/**********************************************************
/* JsonDeserializer implementation
/**********************************************************
*/
protected final Object finishBuild(DeserializationContext ctxt, Object builder)
throws IOException
{
try {
return _buildMethod.getMember().invoke(builder);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null;
}
}
/**
* Main deserialization method for bean-based objects (POJOs).
*/
@Override
public final Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
// common case first:
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
if (_vanillaProcessing) {
return finishBuild(ctxt, vanillaDeserialize(jp, ctxt, t));
}
Object builder =
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> return deserializeWithView(jp, ctxt, builder, view);
}
}
JsonToken t = jp.getCurrentToken();
// 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
builder = prop.deserializeSetAndReturn(jp, ctxt, builder);
} catch (Exception e) {
wrapAndThrow(e, builder, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, handledType(), propName);
}
return builder;
}
/**
* Streamlined version that is only used when no "special"
* features are enabled.
*/
private final Object vanillaDeserialize(JsonParser jp,
DeserializationContext ctxt, JsonToken t)
throws IOException, JsonProcessingException
{
Object bean = _valueInstantiator.createUsingDefault(ctxt);
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
} else {
handleUnknownVanilla(jp, ctxt, bean, propName);
}
}
return bean;
}
/**
* General version used when handling needs more advanced
* features.
*/
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_nonStandardCreation) {
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(jp, ctxt);
}
if (_externalTypeId
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Handler != null) {
return deserializeWithExternalTypeId(jp, ctxt);
}
return deserializeFromObjectUsingNonDefault(jp, ctxt);
}
Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (_injectables != null) {
injectValues(ctxt, bean);
}
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(jp, ctxt, bean, view);
}
}
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/**
* Method called to deserialize bean using "property-based creator":
* this means that a non-default constructor or factory method is
* called, and then possibly other setters. The trick is that
* values for creator method need to be buffered, first; and
* due to non-guaranteed ordering possibly some other properties
* as well.
*/
@Override
@SuppressWarnings("resource")
protected final Object _deserializeUsingPropertyBased(final JsonParser jp,
final DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
// 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
TokenBuffer unknown = null;
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(jp, ctxt, bean, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
bean = handleUnknownProperties(ctxt, bean, unknown);
}
// or just clean?
return _deserialize(jp, ctxt, bean);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
// As per [JACKSON-313], things marked as ignorable should not be
// passed to any setter
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, handledType(), propName);
continue;
}
// "any property"?
if (_anySetter != null) {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
continue;
}
// Ok then, let's collect the whole field; name and value
if (unknown == null) {
unknown = new TokenBuffer(jp);
}
unknown.writeFieldName(propName);
unknown.copyCurrentStructure(jp);
}
// We hit END_OBJECT, so:
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> if (unknown != null) {
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(null, ctxt, bean, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, bean, unknown);
}
return bean;
}
/*
/**********************************************************
/* Deserializing when we have to consider an active View
/**********************************************************
*/
protected final Object deserializeWithView(JsonParser jp, DeserializationContext ctxt,
Object bean, Class<?> activeView)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
if (!prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/*
/**********************************************************
/* Handling for cases where we have "unwrapped" values
/**********************************************************
*/
/**
* Method called when there are declared "unwrapped" properties
* which need special handling
*/
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
}
if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithUnwrapped(jp, ctxt);
}
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (_injectables != null) {
injectValues(ctxt, bean);
}
final Class<?> activeView = _needViewProcesing ? ctxt.
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>getActiveView() : null;
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser jp,
DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
SettableBeanProperty prop = _beanProperties.find(propName);
jp.nextToken();
if (prop != null) { // normal case
if (activeView != null && !
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser jp,
DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// if so, need to copy all remaining tokens into buffer
while (t
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> == JsonToken.FIELD_NAME) {
jp.nextToken(); // to skip name
tokens.copyCurrentStructure(jp);
t = jp.nextToken();
}
tokens.writeEndObject();
if (bean.getClass() != _beanType.getRawClass()) {
// !!! 08-Jul-2011, tatu: Could probably support; but for now
// it's too complicated, so bail out
throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
}
return _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, handledType(), propName);
continue;
}
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// "any property"?
if (_anySetter != null) {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
}
}
// We hit END_OBJECT, so:
Object bean;
// !!! 15-Feb-2012, tatu: Need to modify creator to use Builder!
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
return _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
}
/*
/**********************************************************
/* Handling for cases where we have property/-ies with
/* external type id
/**********************************************************
*/
protected Object deserializeWithExternalTypeId(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithExternalTypeId(jp, ctxt);
}
return deserializeWithExternalTypeId(jp
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, ctxt, _valueInstantiator.createUsingDefault(ctxt));
}
protected Object deserializeWithExternalTypeId(JsonParser jp,
DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
final ExternalTypeHandler ext = _externalTypeIdHandler.start();
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
bean = prop.deserializeSetAndReturn(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but others are likely to be part of external type id thingy...
if (ext.handlePropertyValue(jp, ctxt, propName, bean)) {
continue;
}
// if not, the usual fallback handling:
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
} else {
// Unknown: let's call handler method
handleUnknownProperty(jp, ctxt, bean, propName);
}
}
// and when we get this far, let's try finalizing the deal:
return ext.complete(jp, ctxt, bean);
}
protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser jp,
DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// !!! 04-Mar-2012, TODO: Need to fix -- will not work as is...
throw new IllegalStateException("Deserialization with Builder, External type id, @Json
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.impl;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class UnknownSerializer
extends StdSerializer<Object>
{
public UnknownSerializer() {
super(Object.class);
}
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonMappingException
{
// 27-Nov-2009, tatu: As per [JACKSON-201] may or may not fail...
if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
failForEmpty(value);
}
// But if it's fine, we'll just output empty JSON Object:
jgen.writeStartObject();
jgen.writeEndObject();
}
@Override
public final void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonGenerationException
{
if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
failForEmpty(value);
}
typeSer.writeTypePrefixForObject(value, jgen);
typeSer.writeTypeSuffixForObject(value, jgen);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {
return null;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectAnyFormat(typeHint);
}
protected void failForEmpty(Object value) throws JsonMappingException
{
throw new JsonMappingException("No serializer found for class "+value.getClass().getName()+" and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )");
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>) {
return new SetterlessProperty(this, newName);
}
@Override
public SetterlessProperty withValueDeserializer(JsonDeserializer<?> deser) {
return new SetterlessProperty(this, deser);
}
/*
/**********************************************************
/* BeanProperty impl
/**********************************************************
*/
@Override
public <A extends Annotation> A getAnnotation(Class<A> acls) {
return _annotated.getAnnotation(acls);
}
@Override public AnnotatedMember getMember() { return _annotated; }
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public final void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
/* Hmmh. Is this a problem? We won't be setting anything, so it's
* equivalent of empty Collection/Map in this case
*/
return;
}
// For [#501] fix we need to implement this but:
if (_valueTypeDeserializer != null) {
throw new JsonMappingException("Problem deserializing 'setterless' property: no way to handle typed deser with setterless yet");
// return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
}
// Ok: then, need to fetch Collection/Map to modify:
Object toModify;
try {
toModify = _getter.invoke(instance);
} catch (Exception e) {
_throwAsIOE(e);
return; // never gets here
}
/* Note: null won't work, since we can't then inject anything
* in. At least that's not good in common case. However,
* theoretically the case where we get JSON null might
* be compatible. If so, implementation could be changed.
*/
if (toModify == null) {
throw new JsonMappingException("Problem deserializing 'setterless' property '"+getName()+"': get method returned null");
}
_valueDeserializer.deserialize(jp, ctxt, toModify);
}
@Override
public Object deserializeSetAndReturn(JsonParser jp,
DeserializationContext ctxt, Object instance) throws IOException, JsonProcessingException
{
deserializeAndSet(jp, ctxt, instance
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.type.*;
/**
* Interface that defines API for simple extensions that can provide additional deserializers
* for various types. Access is by a single callback method; instance is to either return
* a configured {@link JsonDeserializer} for specified type, or null to indicate that it
* does not support handling of the type. In latter case, further calls can be made
* for other providers; in former case returned deserializer is used for handling of
* instances of specified type.
*<p>
* Unlike with {@link com.fasterxml.jackson.databind.ser.Serializers},
* multiple different methods are used since different kinds of types typically
* require different kinds of inputs.
*/
public interface Deserializers
{
/**
* Method called to locate serializer for specified array type.
*<p>
* Deserializer for element type may be passed, if configured explicitly at higher level (by
* annotations, typically), but usually are not.
* Type deserializer for element is passed if one is needed based on contextual information
* (annotations on declared element class; or on field or method type is associated with).
*
* @param type Type of array instances to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
* @param elementTypeDeserializer If element type needs polymorphic type handling, this is
* the type information deserializer to use; should usually be used as is when constructing
* array deserializer.
* @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using
* annotations, for exmple). May be null, in which case it should be resolved here (or using
* {@link ResolvableDeserializer} callback)
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findArrayDeserializer(ArrayType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException;
/**
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
* Method called to locate serializer for specified {@link java.util.Collection} (List, Set etc) type.
*<p>
* Deserializer for element type may be passed, if configured explicitly at higher level (by
* annotations, typically), but usually are not.
* Type deserializer for element is passed if one is needed based on contextual information
* (annotations on declared element class; or on field or method type is associated with).
*
* @param type Type of collection instances to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
* @param elementTypeDeserializer If element type needs polymorphic type handling, this is
* the type information deserializer to use; should usually be used as is when constructing
* array deserializer.
* @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using
* annotations, for exmple). May be null, in which case it should be resolved here (or using
* {@link ResolvableDeserializer} callback)
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findCollectionDeserializer(CollectionType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException;
/**
* Method called to locate serializer for specified
* "Collection-like" type (one that acts
* like {@link java.util.Collection} but does not implement it).
*<p>
* Deserializer for element type may be passed, if configured explicitly at higher level (by
* annotations, typically), but usually are not.
* Type deserializer for element is passed if one is needed based on contextual information
* (annotations on declared element class; or on field or method type is associated with).
*
* @param type Type of instances to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
* @param elementTypeDeserializer If element type needs polymorphic type handling, this is
* the type information deserializer to use; should usually be used as is
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> when constructing
* array deserializer.
* @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using
* annotations, for exmple). May be null, in which case it should be resolved here (or using
* {@link ResolvableDeserializer} callback)
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException;
/**
* Method called to locate deserializer for specified {@link java.lang.Enum} type.
*
* @param type Type of {@link java.lang.Enum} instances to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findEnumDeserializer(Class<?> type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException;
/**
* Method called to locate deserializer for specified {@link java.util.Map} type.
*<p>
* Deserializer for element type may be passed, if configured explicitly at higher level (by
* annotations, typically), but usually are not.
* Type deserializer for element is passed if one is needed based on contextual information
* (annotations on declared element class; or on field or method type is associated with).
*<p>
* Similarly, a {@link KeyDeserializer} may be passed, but this is only done if there is
* a specific configuration override (annotations) to indicate instance to use.
* Otherwise null is passed, and key deserializer needs to be obtained later during
* resolution (using {@link ResolvableDeserializer#resolve}).
*
* @param type Type of {@link java.util.Map} instances to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
* @param keyDeserializer Key deserializer use, if it is defined
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> via annotations or other configuration;
* null if default key deserializer for key type can be used.
* @param elementTypeDeserializer If element type needs polymorphic type handling, this is
* the type information deserializer to use; should usually be used as is when constructing
* array deserializer.
* @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using
* annotations, for exmple). May be null, in which case it should be resolved here (or using
* {@link ResolvableDeserializer} callback)
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findMapDeserializer(MapType type,
DeserializationConfig config, BeanDescription beanDesc,
KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException;
/**
* Method called to locate serializer for specified
* "Map-like" type (one that acts
* like {@link java.util.Map} but does not implement it).
*<p>
* Deserializer for element type may be passed, if configured explicitly at higher level (by
* annotations, typically), but usually are not.
* Type deserializer for element is passed if one is needed based on contextual information
* (annotations on declared element class; or on field or method type is associated with).
*<p>
* Similarly, a {@link KeyDeserializer} may be passed, but this is only done if there is
* a specific configuration override (annotations) to indicate instance to use.
* Otherwise null is passed, and key deserializer needs to be obtained later during
* resolution (using {@link ResolvableDeserializer#resolve}).
*
* @param type Type of {@link java.util.Map} instances to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
* @param keyDeserializer Key deserializer use, if it is defined via annotations or other configuration;
* null if default key deserializer for key type can be used.
* @param elementTypeDeserializer If element type needs polymorphic type handling, this is
* the type information deserializer to use; should usually be used as
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> is when constructing
* array deserializer.
* @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using
* annotations, for exmple). May be null, in which case it should be resolved here (or using
* {@link ResolvableDeserializer} callback)
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException;
/**
* Method called to locate deserializer for specified JSON tree node type.
*
* @param nodeType Specific type of JSON tree nodes to deserialize
* (subtype of {@link com.fasterxml.jackson.databind.JsonNode})
* @param config Configuration in effect
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException;
/**
* Method called to locate deserializer for specified value type which does not belong to any other
* category (not an Enum, Collection, Map, Array or tree node)
*
* @param type Bean type to deserialize
* @param config Configuration in effect
* @param beanDesc Definition of the enumeration type that contains class annotations and
* other information typically needed for building deserializers
*
* @return Deserializer to use for the type; or null if this provider does not know how to construct it
*/
public JsonDeserializer<?> findBeanDeserializer(JavaType type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException;
/*
/**********************************************************
/* Helper classes
/**********************************************************
*/
/**
* Basic {@link Deserializers} implementation that implements all methods but provides
* no deserializers. Its main purpose is to serve as a base class so that
* sub-classes only need to override methods they need, as most of the time some
* of methods are not needed (especially enumeration and array deserializers are
* very rarely overridden).
*/
public static class Base implements Deserial
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>izers
{
@Override
public JsonDeserializer<?> findArrayDeserializer(ArrayType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findCollectionDeserializer(CollectionType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findMapDeserializer(MapType type,
DeserializationConfig config, BeanDescription beanDesc,
KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findEnumDeserializer(Class<?> type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
return null;
}
@Override
public JsonDeserializer<?> findBeanDeserializer(JavaType type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
return null;
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser;
import com.fasterxml.jackson.databind.*;
/**
* Interface used to indicate serializers that want to do post-processing
* after construction and being added to {@link SerializerProvider},
* but before being used. This is typically used to resolve references
* to other contained types; for example, bean serializers use this
* to eagerly find serializers for contained field types.
*<p>
* Note that in cases where serializer needs both contextualization and
* resolution -- that is, implements both this interface and {@link ContextualSerializer}
* -- resolution via this interface occurs first, and contextual
* resolution (using {@link ContextualSerializer}) later on.
*/
public interface ResolvableSerializer
{
/**
* Method called after {@link SerializerProvider} has registered
* the serializer, but before it has returned it to the caller.
* Called object can then resolve its dependencies to other types,
* including self-references (direct or indirect).
*<p>
* Note that this method does NOT return serializer, since resolution
* is not allowed to change actual serializer to use.
*
* @param provider Provider that has constructed serializer this method
* is called on.
*/
public abstract void resolve(SerializerProvider provider)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>> A getAnnotation(Class<A> acls) {
return _delegate.getAnnotation(acls);
}
@Override public AnnotatedMember getMember() { return _delegate.getMember(); }
/*
/**********************************************************
/* Deserialization methods
/**********************************************************
*/
@Override
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object bean)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
Object value;
if (t == JsonToken.VALUE_NULL) {
value = (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt);
} else if (_valueTypeDeserializer != null) {
value = _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
} else { // the usual case
try {
value = _creator.newInstance(bean);
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+_creator.getDeclaringClass().getName()+", problem: "+e.getMessage());
value = null;
}
_valueDeserializer.deserialize(jp, ctxt, value);
}
set(bean, value);
}
@Override
public Object deserializeSetAndReturn(JsonParser jp,
DeserializationContext ctxt, Object instance)
throws IOException, JsonProcessingException
{
return setAndReturn(instance, deserialize(jp, ctxt));
}
@Override
public final void set(Object instance, Object value) throws IOException
{
_delegate.set(instance, value);
}
@Override
public Object setAndReturn(Object instance, Object value)
throws IOException
{
return _delegate.setAndReturn(instance, value);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> shareable thread-safe instance which has no additional custom deserializers
* registered
*/
public final static BeanDeserializerFactory instance = new BeanDeserializerFactory(
new DeserializerFactoryConfig());
public BeanDeserializerFactory(DeserializerFactoryConfig config) {
super(config);
}
/**
* Method used by module registration functionality, to construct a new bean
* deserializer factory
* with different configuration settings.
*/
@Override
public DeserializerFactory withConfig(DeserializerFactoryConfig config)
{
if (_factoryConfig == config) {
return this;
}
/* 22-Nov-2010, tatu: Handling of subtypes is tricky if we do immutable-with-copy-ctor;
* and we pretty much have to here either choose between losing subtype instance
* when registering additional deserializers, or losing deserializers.
* Instead, let's actually just throw an error if this method is called when subtype
* has not properly overridden this method; this to indicate problem as soon as possible.
*/
if (getClass() != BeanDeserializerFactory.class) {
throw new IllegalStateException("Subtype of BeanDeserializerFactory ("+getClass().getName()
+") has not properly overridden method 'withAdditionalDeserializers': can not instantiate subtype with "
+"additional deserializer definitions");
}
return new BeanDeserializerFactory(config);
}
/*
/**********************************************************
/* Overrides for super-class methods used for finding
/* custom deserializers
/**********************************************************
*/
// Note: NOT overriding, superclass has no matching method
@SuppressWarnings("unchecked")
protected JsonDeserializer<Object> _findCustomBeanDeserializer(JavaType type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findBeanDeserializer(type, config, beanDesc);
if (deser != null) {
return (JsonDeserializer<Object>) deser;
}
}
return null;
}
/*
/**********************************************************
/* DeserializerFactory API implementation
/**********************************************************
*/
/**
* Method that {@link DeserializerCache}s call to create a new
* deserializer for types other than Collections, Maps, arrays and
* enums.
*/
@Override
public JsonDeserializer<Object> createBean
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Deserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
// We may also have custom overrides:
JsonDeserializer<Object> custom = _findCustomBeanDeserializer(type, config, beanDesc);
if (custom != null) {
return custom;
}
/* One more thing to check: do we have an exception type
* (Throwable or its sub-classes)? If so, need slightly
* different handling.
*/
if (type.isThrowable()) {
return buildThrowableDeserializer(ctxt, type, beanDesc);
}
/* Or, for abstract types, may have alternate means for resolution
* (defaulting, materialization)
*/
if (type.isAbstract()) {
// [JACKSON-41] (v1.6): Let's make it possible to materialize abstract types.
JavaType concreteType = materializeAbstractType(ctxt, type, beanDesc);
if (concreteType != null) {
/* important: introspect actual implementation (abstract class or
* interface doesn't have constructors, for one)
*/
beanDesc = config.introspect(concreteType);
return buildBeanDeserializer(ctxt, concreteType, beanDesc);
}
}
// Otherwise, may want to check handlers for standard types, from superclass:
@SuppressWarnings("unchecked")
JsonDeserializer<Object> deser = (JsonDeserializer<Object>) findStdDeserializer(ctxt, type, beanDesc);
if (deser != null) {
return deser;
}
// Otherwise: could the class be a Bean class? If not, bail out
if (!isPotentialBeanType(type.getRawClass())) {
return null;
}
// Use generic bean introspection to build deserializer
return buildBeanDeserializer(ctxt, type, beanDesc);
}
@Override
public JsonDeserializer<Object> createBuilderBasedDeserializer(
DeserializationContext ctxt, JavaType valueType, BeanDescription beanDesc,
Class<?> builderClass)
throws JsonMappingException
{
// First: need a BeanDescription for builder class
JavaType builderType = ctxt.constructType(builderClass);
BeanDescription builderDesc = ctxt.getConfig().introspectForBuilder(builderType);
return buildBuilderBasedDeserializer(ctxt, valueType
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, builderDesc);
}
/**
* Method called by {@link BeanDeserializerFactory} to see if there might be a standard
* deserializer registered for given type.
*/
protected JsonDeserializer<?> findStdDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
// note: we do NOT check for custom deserializers here, caller has already
// done that
JsonDeserializer<?> deser = findDefaultDeserializer(ctxt, type, beanDesc);
if (deser != null) {
return deser;
}
Class<?> cls = type.getRawClass();
// [JACKSON-283]: AtomicReference is a rather special type...
if (AtomicReference.class.isAssignableFrom(cls)) {
// Must find parameterization
TypeFactory tf = ctxt.getTypeFactory();
JavaType[] params = tf.findTypeParameters(type, AtomicReference.class);
JavaType referencedType;
if (params == null || params.length < 1) { // untyped (raw)
referencedType = TypeFactory.unknownType();
} else {
referencedType = params[0];
}
TypeDeserializer valueTypeDeser = findTypeDeserializer(ctxt.getConfig(), referencedType);
BeanDescription refdDesc = ctxt.getConfig().introspectClassAnnotations(referencedType);
deser = findDeserializerFromAnnotation(ctxt, refdDesc.getClassInfo());
return new AtomicReferenceDeserializer(referencedType, valueTypeDeser, deser);
}
return findOptionalStdDeserializer(ctxt, type, beanDesc);
}
/**
* Overridable method called after checking all other types.
*
* @since 2.2
*/
protected JsonDeserializer<?> findOptionalStdDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
return OptionalHandlerFactory.instance.findDeserializer(type, ctxt.getConfig(), beanDesc);
}
protected JavaType materializeAbstractType(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
final JavaType abstractType = beanDesc.getType();
// [JACKSON-502]: Now it is possible to have multiple resolvers too,
// as they are registered via module interface.
for (AbstractTypeResolver r : _factoryConfig.abstractTypeResolvers
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>()) {
JavaType concrete = r.resolveAbstractType(ctxt.getConfig(), abstractType);
if (concrete != null) {
return concrete;
}
}
return null;
}
/*
/**********************************************************
/* Public construction method beyond DeserializerFactory API:
/* can be called from outside as well as overridden by
/* sub-classes
/**********************************************************
*/
/**
* Method that is to actually build a bean deserializer instance.
* All basic sanity checks have been done to know that what we have
* may be a valid bean type, and that there are no default simple
* deserializers.
*/
@SuppressWarnings("unchecked")
public JsonDeserializer<Object> buildBeanDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
// First: check what creators we can use, if any
ValueInstantiator valueInstantiator = findValueInstantiator(ctxt, beanDesc);
BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, beanDesc);
builder.setValueInstantiator(valueInstantiator);
// And then setters for deserializing from JSON Object
addBeanProps(ctxt, beanDesc, builder);
addObjectIdReader(ctxt, beanDesc, builder);
// managed/back reference fields/setters need special handling... first part
addReferenceProperties(ctxt, beanDesc, builder);
addInjectables(ctxt, beanDesc, builder);
final DeserializationConfig config = ctxt.getConfig();
// [JACKSON-440]: update builder now that all information is in?
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
builder = mod.updateBuilder(config, beanDesc, builder);
}
}
JsonDeserializer<?> deserializer;
/* 19-Mar-2012, tatu: This check used to be done earlier; but we have to defer
* it a bit to collect information on ObjectIdReader, for example.
*/
if (type.isAbstract() && !valueInstantiator.canInstantiate()) {
deserializer = builder.buildAbstract();
} else {
deserializer = builder.build();
}
// [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> built:
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deserializer = mod.modifyDeserializer(config, beanDesc, deserializer);
}
}
return (JsonDeserializer<Object>) deserializer;
}
/**
* Method for constructing a bean deserializer that uses specified
* intermediate Builder for binding data, and construction of the
* value instance.
* Note that implementation is mostly copied from the regular
* BeanDeserializer build method.
*/
@SuppressWarnings("unchecked")
protected JsonDeserializer<Object> buildBuilderBasedDeserializer(
DeserializationContext ctxt, JavaType valueType, BeanDescription builderDesc)
throws JsonMappingException
{
// Creators, anyone? (to create builder itself)
ValueInstantiator valueInstantiator = findValueInstantiator(ctxt, builderDesc);
final DeserializationConfig config = ctxt.getConfig();
BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, builderDesc);
builder.setValueInstantiator(valueInstantiator);
// And then "with methods" for deserializing from JSON Object
addBeanProps(ctxt, builderDesc, builder);
addObjectIdReader(ctxt, builderDesc, builder);
// managed/back reference fields/setters need special handling... first part
addReferenceProperties(ctxt, builderDesc, builder);
addInjectables(ctxt, builderDesc, builder);
JsonPOJOBuilder.Value builderConfig = builderDesc.findPOJOBuilderConfig();
final String buildMethodName = (builderConfig == null) ?
"build" : builderConfig.buildMethodName;
// and lastly, find build method to use:
AnnotatedMethod buildMethod = builderDesc.findMethod(buildMethodName, null);
if (buildMethod != null) { // note: can't yet throw error; may be given build method
if (config.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(buildMethod.getMember());
}
}
builder.setPOJOBuilder(buildMethod, builderConfig);
// this may give us more information...
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
builder = mod.updateBuilder(config, builderDesc, builder);
}
}
JsonDeserializer<?> deserializer = builder
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.buildBuilderBased(
valueType, buildMethodName);
// [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just built:
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deserializer = mod.modifyDeserializer(config, builderDesc, deserializer);
}
}
return (JsonDeserializer<Object>) deserializer;
}
protected void addObjectIdReader(DeserializationContext ctxt,
BeanDescription beanDesc, BeanDeserializerBuilder builder)
throws JsonMappingException
{
ObjectIdInfo objectIdInfo = beanDesc.getObjectIdInfo();
if (objectIdInfo == null) {
return;
}
Class<?> implClass = objectIdInfo.getGeneratorType();
JavaType idType;
SettableBeanProperty idProp;
ObjectIdGenerator<?> gen;
ObjectIdResolver resolver = ctxt.objectIdResolverInstance(beanDesc.getClassInfo(), objectIdInfo);
// Just one special case: Property-based generator is trickier
if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work
PropertyName propName = objectIdInfo.getPropertyName();
idProp = builder.findProperty(propName);
if (idProp == null) {
throw new IllegalArgumentException("Invalid Object Id definition for "
+beanDesc.getBeanClass().getName()+": can not find property with name '"+propName+"'");
}
idType = idProp.getType();
gen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope());
} else {
JavaType type = ctxt.constructType(implClass);
idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
idProp = null;
gen = ctxt.objectIdGeneratorInstance(beanDesc.getClassInfo(), objectIdInfo);
}
// also: unlike with value deserializers, let's just resolve one we need here
JsonDeserializer<?> deser = ctxt.findRootValueDeserializer(idType);
builder.setObjectIdReader(ObjectIdReader.construct(idType,
objectIdInfo.getPropertyName(), gen, deser, idProp, resolver));
}
@SuppressWarnings("unchecked")
public JsonDeserializer<Object> buildThrowableDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription bean
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Desc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
// first: construct like a regular bean deserializer...
BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, beanDesc);
builder.setValueInstantiator(findValueInstantiator(ctxt, beanDesc));
addBeanProps(ctxt, beanDesc, builder);
// (and assume there won't be any back references)
// But then let's decorate things a bit
/* To resolve [JACKSON-95], need to add "initCause" as setter
* for exceptions (sub-classes of Throwable).
*/
AnnotatedMethod am = beanDesc.findMethod("initCause", INIT_CAUSE_PARAMS);
if (am != null) { // should never be null
SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(ctxt.getConfig(), am, "cause");
SettableBeanProperty prop = constructSettableProperty(ctxt, beanDesc, propDef,
am.getGenericParameterType(0));
if (prop != null) {
/* 21-Aug-2011, tatus: We may actually have found 'cause' property
* to set (with new 1.9 code)... but let's replace it just in case,
* otherwise can end up with odd errors.
*/
builder.addOrReplaceProperty(prop, true);
}
}
// And also need to ignore "localizedMessage"
builder.addIgnorable("localizedMessage");
// [JACKSON-794]: JDK 7 also added "getSuppressed", skip if we have such data:
builder.addIgnorable("suppressed");
/* As well as "message": it will be passed via constructor,
* as there's no 'setMessage()' method
*/
builder.addIgnorable("message");
// [JACKSON-440]: update builder now that all information is in?
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
builder = mod.updateBuilder(config, beanDesc, builder);
}
}
JsonDeserializer<?> deserializer = builder.build();
/* At this point it ought to be a BeanDeserializer; if not, must assume
* it's some other thing that can
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> handle deserialization ok...
*/
if (deserializer instanceof BeanDeserializer) {
deserializer = new ThrowableDeserializer((BeanDeserializer) deserializer);
}
// [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just built:
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deserializer = mod.modifyDeserializer(config, beanDesc, deserializer);
}
}
return (JsonDeserializer<Object>) deserializer;
}
/*
/**********************************************************
/* Helper methods for Bean deserializer construction,
/* overridable by sub-classes
/**********************************************************
*/
/**
* Overridable method that constructs a {@link BeanDeserializerBuilder}
* which is used to accumulate information needed to create deserializer
* instance.
*/
protected BeanDeserializerBuilder constructBeanDeserializerBuilder(DeserializationContext ctxt,
BeanDescription beanDesc) {
return new BeanDeserializerBuilder(beanDesc, ctxt.getConfig());
}
/**
* Method called to figure out settable properties for the
* bean deserializer to use.
*<p>
* Note: designed to be overridable, and effort is made to keep interface
* similar between versions.
*/
protected void addBeanProps(DeserializationContext ctxt,
BeanDescription beanDesc, BeanDeserializerBuilder builder)
throws JsonMappingException
{
final SettableBeanProperty[] creatorProps =
builder.getValueInstantiator().getFromObjectArguments(ctxt.getConfig());
// Things specified as "ok to ignore"? [JACKSON-77]
AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
boolean ignoreAny = false;
{
Boolean B = intr.findIgnoreUnknownProperties(beanDesc.getClassInfo());
if (B != null) {
ignoreAny = B.booleanValue();
builder.setIgnoreUnknownProperties(ignoreAny);
}
}
// Or explicit/implicit definitions?
Set<String> ignored = ArrayBuilders.arrayToSet(intr.findPropertiesToIgnore(beanDesc.getClassInfo()));
for (String propName : ignored) {
builder.addIgnorable(propName);
}
// Also, do we have a fallback "any" setter?
AnnotatedMethod anySetter = beanDesc.findAny
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>orable types".
* Note that this will not remove properties that have no
* setters.
*/
protected List<BeanPropertyDefinition> filterBeanProps(DeserializationContext ctxt,
BeanDescription beanDesc, BeanDeserializerBuilder builder,
List<BeanPropertyDefinition> propDefsIn,
Set<String> ignored)
throws JsonMappingException
{
ArrayList<BeanPropertyDefinition> result = new ArrayList<BeanPropertyDefinition>(
Math.max(4, propDefsIn.size()));
HashMap<Class<?>,Boolean> ignoredTypes = new HashMap<Class<?>,Boolean>();
// These are all valid setters, but we do need to introspect bit more
for (BeanPropertyDefinition property : propDefsIn) {
String name = property.getName();
if (ignored.contains(name)) { // explicit ignoral using @JsonIgnoreProperties needs to block entries
continue;
}
if (!property.hasConstructorParameter()) { // never skip constructor params
Class<?> rawPropertyType = null;
if (property.hasSetter()) {
rawPropertyType = property.getSetter().getRawParameterType(0);
} else if (property.hasField()) {
rawPropertyType = property.getField().getRawType();
}
// [JACKSON-429] Some types are declared as ignorable as well
if ((rawPropertyType != null)
&& (isIgnorableType(ctxt.getConfig(), beanDesc, rawPropertyType, ignoredTypes))) {
// important: make ignorable, to avoid errors if value is actually seen
builder.addIgnorable(name);
continue;
}
}
result.add(property);
}
return result;
}
/**
* Method that will find if bean has any managed- or back-reference properties,
* and if so add them to bean, to be linked during resolution phase.
*/
protected void addReferenceProperties(DeserializationContext ctxt,
BeanDescription beanDesc, BeanDeserializerBuilder builder)
throws JsonMappingException
{
// and then back references, not necessarily found as regular properties
Map<String,AnnotatedMember> refs = beanDesc.findBackReferenceProperties();
if (refs != null) {
for (Map.Entry<String, AnnotatedMember> en : refs.entrySet()) {
String name = en.getKey();
AnnotatedMember m = en.getValue();
Type genericType;
if (m
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> instanceof AnnotatedMethod) {
genericType = ((AnnotatedMethod) m).getGenericParameterType(0);
} else {
genericType = m.getRawType();
}
SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(
ctxt.getConfig(), m);
builder.addBackReferenceProperty(name, constructSettableProperty(
ctxt, beanDesc, propDef, genericType));
}
}
}
/**
* Method called locate all members used for value injection (if any),
* constructor {@link com.fasterxml.jackson.databind.deser.impl.ValueInjector} instances, and add them to builder.
*/
protected void addInjectables(DeserializationContext ctxt,
BeanDescription beanDesc, BeanDeserializerBuilder builder)
throws JsonMappingException
{
Map<Object, AnnotatedMember> raw = beanDesc.findInjectables();
if (raw != null) {
boolean fixAccess = ctxt.canOverrideAccessModifiers();
for (Map.Entry<Object, AnnotatedMember> entry : raw.entrySet()) {
AnnotatedMember m = entry.getValue();
if (fixAccess) {
m.fixAccess(); // to ensure we can call it
}
builder.addInjectable(new PropertyName(m.getName()),
beanDesc.resolveType(m.getGenericType()),
beanDesc.getClassAnnotations(), m, entry.getKey());
}
}
}
/**
* Method called to construct fallback {@link SettableAnyProperty}
* for handling unknown bean properties, given a method that
* has been designated as such setter.
*/
protected SettableAnyProperty constructAnySetter(DeserializationContext ctxt,
BeanDescription beanDesc, AnnotatedMethod setter)
throws JsonMappingException
{
if (ctxt.canOverrideAccessModifiers()) {
setter.fixAccess(); // to ensure we can call it
}
// we know it's a 2-arg method, second arg is the value
JavaType type = beanDesc.bindingsForBeanType().resolveType(setter.getGenericParameterType(1));
BeanProperty.Std property = new BeanProperty.Std(new PropertyName(setter.getName()),
type, null, beanDesc.getClassAnnotations(), setter,
PropertyMetadata.STD_OPTIONAL);
type = resolveType(ctxt, beanDesc, type, setter);
/* AnySetter can be
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> annotated with @JsonClass (etc) just like a
* regular setter... so let's see if those are used.
* Returns null if no annotations, in which case binding will
* be done at a later point.
*/
JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, setter);
/* Otherwise, method may specify more specific (sub-)class for
* value (no need to check if explicit deser was specified):
*/
type = modifyTypeByAnnotation(ctxt, setter, type);
if (deser == null) {
deser = type.getValueHandler();
}
TypeDeserializer typeDeser = type.getTypeHandler();
return new SettableAnyProperty(property, setter, type,
deser, typeDeser);
}
/**
* Method that will construct a regular bean property setter using
* the given setter method.
*
* @return Property constructed, if any; or null to indicate that
* there should be no property based on given definitions.
*/
protected SettableBeanProperty constructSettableProperty(DeserializationContext ctxt,
BeanDescription beanDesc, BeanPropertyDefinition propDef,
Type jdkType)
throws JsonMappingException
{
// need to ensure method is callable (for non-public)
AnnotatedMember mutator = propDef.getNonConstructorMutator();
if (ctxt.canOverrideAccessModifiers()) {
mutator.fixAccess();
}
// note: this works since we know there's exactly one argument for methods
JavaType t0 = beanDesc.resolveType(jdkType);
BeanProperty.Std property = new BeanProperty.Std(propDef.getFullName(),
t0, propDef.getWrapperName(),
beanDesc.getClassAnnotations(), mutator, propDef.getMetadata());
JavaType type = resolveType(ctxt, beanDesc, t0, mutator);
// did type change?
if (type != t0) {
property = property.withType(type);
}
/* First: does the Method specify the deserializer to use?
* If so, let's use it.
*/
JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, mutator);
type = modifyTypeByAnnotation(ctxt, mutator, type);
TypeDeserializer typeDeser = type.getTypeHandler();
SettableBeanProperty prop;
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
if (mutator instanceof AnnotatedMethod) {
prop = new MethodProperty(propDef, type, typeDeser,
beanDesc.getClassAnnotations(), (AnnotatedMethod) mutator);
} else {
prop = new FieldProperty(propDef, type, typeDeser,
beanDesc.getClassAnnotations(), (AnnotatedField) mutator);
}
if (propDeser != null) {
prop = prop.withValueDeserializer(propDeser);
}
// [JACKSON-235]: need to retain name of managed forward references:
AnnotationIntrospector.ReferenceProperty ref = propDef.findReferenceType();
if (ref != null && ref.isManagedReference()) {
prop.setManagedReferenceName(ref.getName());
}
ObjectIdInfo objectIdInfo = propDef.findObjectIdInfo();
if(objectIdInfo != null){
prop.setObjectIdInfo(objectIdInfo);
}
return prop;
}
/**
* Method that will construct a regular bean property setter using
* the given setter method.
*/
protected SettableBeanProperty constructSetterlessProperty(DeserializationContext ctxt,
BeanDescription beanDesc, BeanPropertyDefinition propDef)
throws JsonMappingException
{
final AnnotatedMethod getter = propDef.getGetter();
// need to ensure it is callable now:
if (ctxt.canOverrideAccessModifiers()) {
getter.fixAccess();
}
/* 26-Jan-2012, tatu: Alas, this complication is still needed to handle
* (or at least work around) local type declarations...
*/
JavaType type = getter.getType(beanDesc.bindingsForBeanType());
/* First: does the Method specify the deserializer to use?
* If so, let's use it.
*/
JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, getter);
type = modifyTypeByAnnotation(ctxt, getter, type);
// As per [Issue#501], need full resolution:
type = resolveType(ctxt, beanDesc, type, getter);
TypeDeserializer typeDeser = type.getTypeHandler();
SettableBeanProperty prop = new SetterlessProperty(propDef, type, typeDeser,
beanDesc.getClassAnnotations(), getter);
if (propDeser != null) {
prop
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser;
import com.fasterxml.jackson.databind.*;
/**
* Add-on interface that {@link JsonSerializer}s can implement to get a callback
* that can be used to create contextual instances of serializer to use for
* handling properties of supported type. This can be useful
* for serializers that can be configured by annotations, or should otherwise
* have differing behavior depending on what kind of property is being serialized.
*<p>
* Note that in cases where serializer needs both contextualization and
* resolution -- that is, implements both this interface and {@link ResolvableSerializer}
* -- resolution via {@link ResolvableSerializer} occurs first, and contextual
* resolution (via this interface) later on.
*/
public interface ContextualSerializer
{
/**
* Method called to see if a different (or differently configured) serializer
* is needed to serialize values of specified property.
* Note that instance that this method is called on is typically shared one and
* as a result method should <b>NOT</b> modify this instance but rather construct
* and return a new instance. This instance should only be returned as-is, in case
* it is already suitable for use.
*
* @param prov Serializer provider to use for accessing config, other serializers
* @param property Method or field that represents the property
* (and is used to access value to serialize).
* Should be available; but there may be cases where caller can not provide it and
* null is passed instead (in which case impls usually pass 'this' serializer as is)
*
* @return Serializer to use for serializing values of specified property;
* may be this instance or a new instance.
*
* @throws JsonMappingException
*/
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializable;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonschema.JsonSerializableSchema;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.type.TypeFactory;
/**
* Generic handler for types that implement {@link JsonSerializable}.
*<p>
* Note: given that this is used for anything that implements
* interface, can not be checked for direct class equivalence.
*/
@JacksonStdImpl
public class SerializableSerializer
extends StdSerializer<JsonSerializable>
{
public final static SerializableSerializer instance = new SerializableSerializer();
// Ugh. Should NOT need this...
private final static AtomicReference<ObjectMapper> _mapperReference = new AtomicReference<ObjectMapper>();
protected SerializableSerializer() { super(JsonSerializable.class); }
@Override
public void serialize(JsonSerializable value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
value.serialize(jgen, provider);
}
@Override
public final void serializeWithType(JsonSerializable value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonGenerationException
{
value.serializeWithType(jgen, provider, typeSer);
}
@Override
@SuppressWarnings("deprecation")
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
ObjectNode objectNode = createObjectNode();
String schemaType = "any";
String objectProperties = null;
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> String itemDefinition = null;
if (typeHint != null) {
Class<?> rawClass = TypeFactory.rawClass(typeHint);
if (rawClass.isAnnotationPresent(JsonSerializableSchema.class)) {
JsonSerializableSchema schemaInfo = rawClass.getAnnotation(JsonSerializableSchema.class);
schemaType = schemaInfo.schemaType();
if (!JsonSerializableSchema.NO_VALUE.equals(schemaInfo.schemaObjectPropertiesDefinition())) {
objectProperties = schemaInfo.schemaObjectPropertiesDefinition();
}
if (!JsonSerializableSchema.NO_VALUE.equals(schemaInfo.schemaItemDefinition())) {
itemDefinition = schemaInfo.schemaItemDefinition();
}
}
}
/* 19-Mar-2012, tatu: geez, this is butt-ugly abonimation of code...
* really, really should not require back ref to an ObjectMapper.
*/
objectNode.put("type", schemaType);
if (objectProperties != null) {
try {
objectNode.put("properties", _getObjectMapper().readTree(objectProperties));
} catch (IOException e) {
throw new JsonMappingException("Failed to parse @JsonSerializableSchema.schemaObjectPropertiesDefinition value");
}
}
if (itemDefinition != null) {
try {
objectNode.put("items", _getObjectMapper().readTree(itemDefinition));
} catch (IOException e) {
throw new JsonMappingException("Failed to parse @JsonSerializableSchema.schemaItemDefinition value");
}
}
// always optional, no need to specify:
//objectNode.put("required", false);
return objectNode;
}
private final static synchronized ObjectMapper _getObjectMapper()
{
ObjectMapper mapper = _mapperReference.get();
if (mapper == null) {
mapper = new ObjectMapper();
_mapperReference.set(mapper);
}
return mapper;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectAnyFormat(typeHint);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>-blueprint instances from the blueprint.
* This is needed to retain state during serialization.
*/
public abstract DefaultSerializerProvider createInstance(SerializationConfig config,
SerializerFactory jsf);
/**
* The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
* for serializing given value, using serializers that
* this provider has access to (via caching and/or creating new serializers
* as need be).
*/
public void serializeValue(JsonGenerator jgen, Object value) throws IOException
{
if (value == null) {
_serializeNull(jgen);
return;
}
Class<?> cls = value.getClass();
// true, since we do want to cache root-level typed serializers (ditto for null property)
final JsonSerializer<Object> ser = findTypedValueSerializer(cls, true, null);
// Ok: should we wrap result in an additional property ("root name")?
final boolean wrap;
String rootName = _config.getRootName();
if (rootName == null) { // not explicitly specified
// [JACKSON-163]
wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
if (wrap) {
PropertyName pname = _rootNames.findRootName(value.getClass(), _config);
jgen.writeStartObject();
jgen.writeFieldName(pname.simpleAsEncoded(_config));
}
} else if (rootName.length() == 0) {
wrap = false;
} else { // [JACKSON-764]
// empty String means explicitly disabled; non-empty that it is enabled
wrap = true;
jgen.writeStartObject();
jgen.writeFieldName(rootName);
}
try {
ser.serialize(value, jgen, this);
if (wrap) {
jgen.writeEndObject();
}
} catch (IOException ioe) { // As per [JACKSON-99], pass IOException and subtypes as-is
throw ioe;
} catch (Exception e) { // but wrap RuntimeExceptions, to get path information
String msg = e.getMessage();
if (msg == null) {
msg = "[no message for "+e.getClass().getName()+"]";
}
throw new JsonMappingException(msg, e);
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
}
}
/**
* The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
* for serializing given value (assumed to be of specified root type,
* instead of runtime type of value),
* using serializers that
* this provider has access to (via caching and/or creating new serializers
* as need be),
*
* @param rootType Type to use for locating serializer to use, instead of actual
* runtime type. Must be actual type, or one of its super types
*/
public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType) throws IOException
{
if (value == null) {
_serializeNull(jgen);
return;
}
// Let's ensure types are compatible at this point
if (!rootType.getRawClass().isAssignableFrom(value.getClass())) {
_reportIncompatibleRootType(value, rootType);
}
// root value, not reached via property:
JsonSerializer<Object> ser = findTypedValueSerializer(rootType, true, null);
// Ok: should we wrap result in an additional property ("root name")?
final boolean wrap;
String rootName = _config.getRootName();
if (rootName == null) { // not explicitly specified
// [JACKSON-163]
wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
if (wrap) {
jgen.writeStartObject();
PropertyName pname = _rootNames.findRootName(value.getClass(), _config);
jgen.writeFieldName(pname.simpleAsEncoded(_config));
}
} else if (rootName.length() == 0) {
wrap = false;
} else { // [JACKSON-764]
// empty String means explicitly disabled; non-empty that it is enabled
wrap = true;
jgen.writeStartObject();
jgen.writeFieldName(rootName);
}
try {
ser.serialize(value, jgen, this);
if (wrap) {
jgen.writeEndObject();
}
} catch (IOException ioe) { // no wrapping for IO (and derived)
throw ioe;
} catch (Exception e) { // but others do need to be, to get path etc
String msg =
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> e.getMessage();
if (msg == null) {
msg = "[no message for "+e.getClass().getName()+"]";
}
throw new JsonMappingException(msg, e);
}
}
/**
* The method to be called by {@link ObjectWriter}
* for serializing given value (assumed to be of specified root type,
* instead of runtime type of value), when it may know specific
* {@link JsonSerializer} to use.
*
* @param rootType Type to use for locating serializer to use, instead of actual
* runtime type, if no serializer is passed
* @param ser Root Serializer to use, if not null
*
* @since 2.1
*/
public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType, JsonSerializer<Object> ser) throws IOException
{
if (value == null) {
_serializeNull(jgen);
return;
}
// Let's ensure types are compatible at this point
if ((rootType != null) && !rootType.getRawClass().isAssignableFrom(value.getClass())) {
_reportIncompatibleRootType(value, rootType);
}
// root value, not reached via property:
if (ser == null) {
ser = findTypedValueSerializer(rootType, true, null);
}
// Ok: should we wrap result in an additional property ("root name")?
final boolean wrap;
String rootName = _config.getRootName();
if (rootName == null) { // not explicitly specified
// [JACKSON-163]
wrap = _config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE);
if (wrap) {
jgen.writeStartObject();
PropertyName pname = (rootType == null)
? _rootNames.findRootName(value.getClass(), _config)
: _rootNames.findRootName(rootType, _config);
jgen.writeFieldName(pname.simpleAsEncoded(_config));
}
} else if (rootName.length() == 0) {
wrap = false;
} else { // [JACKSON-764]
// empty String means explicitly disabled; non-empty that it is enabled
wrap = true;
jgen.writeStartObject();
jgen.writeFieldName(
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>rootName);
}
try {
ser.serialize(value, jgen, this);
if (wrap) {
jgen.writeEndObject();
}
} catch (IOException ioe) { // no wrapping for IO (and derived)
throw ioe;
} catch (Exception e) { // but others do need to be, to get path etc
String msg = e.getMessage();
if (msg == null) {
msg = "[no message for "+e.getClass().getName()+"]";
}
throw new JsonMappingException(msg, e);
}
}
/**
* Helper method called when root value to serialize is null
*
* @since 2.3
*/
protected void _serializeNull(JsonGenerator jgen) throws IOException
{
JsonSerializer<Object> ser = getDefaultNullValueSerializer();
try {
ser.serialize(null, jgen, this);
} catch (IOException ioe) { // no wrapping for IO (and derived)
throw ioe;
} catch (Exception e) { // but others do need to be, to get path etc
String msg = e.getMessage();
if (msg == null) {
msg = "[no message for "+e.getClass().getName()+"]";
}
throw new JsonMappingException(msg, e);
}
}
/**
* The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
* to generate <a href="http://json-schema.org/">JSON schema</a> for
* given type.
*
* @param type The type for which to generate schema
*/
@SuppressWarnings("deprecation")
public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class<?> type)
throws JsonMappingException
{
if (type == null) {
throw new IllegalArgumentException("A class must be provided");
}
/* no need for embedded type information for JSON schema generation (all
* type information it needs is accessible via "untyped" serializer)
*/
JsonSerializer<Object> ser = findValueSerializer(type, null);
JsonNode schemaNode = (ser instanceof SchemaAware) ?
((SchemaAware) ser).getSchema(this, null) : com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
if (!(schemaNode instanceof ObjectNode)) {
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> throw new IllegalArgumentException("Class " + type.getName()
+" would not be serialized as a JSON object and therefore has no schema");
}
return new com.fasterxml.jackson.databind.jsonschema.JsonSchema((ObjectNode) schemaNode);
}
/**
* The method to be called by {@link ObjectMapper} and {@link ObjectWriter}
* to to expose the format of the given to to the given visitor
*
* @param javaType The type for which to generate format
* @param visitor the visitor to accept the format
*/
public void acceptJsonFormatVisitor(JavaType javaType, JsonFormatVisitorWrapper visitor)
throws JsonMappingException
{
if (javaType == null) {
throw new IllegalArgumentException("A class must be provided");
}
/* no need for embedded type information for JSON schema generation (all
* type information it needs is accessible via "untyped" serializer)
*/
visitor.setProvider(this);
findValueSerializer(javaType, null).acceptJsonFormatVisitor(visitor, javaType);
}
@Deprecated // since 2.3; use the overloaded variant
public boolean hasSerializerFor(Class<?> cls) {
return hasSerializerFor(cls, null);
}
/**
* Method that can be called to see if this serializer provider
* can find a serializer for an instance of given class.
*<p>
* Note that no Exceptions are thrown, including unchecked ones:
* implementations are to swallow exceptions if necessary.
*/
public boolean hasSerializerFor(Class<?> cls, AtomicReference<Throwable> cause)
{
try {
JsonSerializer<?> ser = _findExplicitUntypedSerializer(cls);
return (ser != null);
} catch (JsonMappingException e) {
if (cause != null) {
cause.set(e);
}
} catch (RuntimeException e) {
if (cause == null) { // earlier behavior
throw e;
}
cause.set(e);
}
return false;
}
/*
/********************************************************
/* Access to caching details
/********************************************************
*/
/**
* Method that can be used to determine how many serializers this
* provider is caching currently
* (if it does caching: default implementation does)
* Exact count depends on what kind of serializers get cached;
* default implementation caches all serializers, including ones that
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> tatu: We may actually want to use equality,
* instead of identity... so:
*/
if (isEnabled(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID)) {
return new HashMap<Object,WritableObjectId>();
}
return new IdentityHashMap<Object,WritableObjectId>();
}
/*
/**********************************************************
/* Factory method impls
/**********************************************************
*/
@Override
public JsonSerializer<Object> serializerInstance(Annotated annotated, Object serDef) throws JsonMappingException
{
if (serDef == null) {
return null;
}
JsonSerializer<?> ser;
if (serDef instanceof JsonSerializer) {
ser = (JsonSerializer<?>) serDef;
} else {
/* Alas, there's no way to force return type of "either class
* X or Y" -- need to throw an exception after the fact
*/
if (!(serDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned serializer definition of type "
+serDef.getClass().getName()+"; expected type JsonSerializer or Class<JsonSerializer> instead");
}
Class<?> serClass = (Class<?>)serDef;
// there are some known "no class" markers to consider too:
if (serClass == JsonSerializer.None.class || ClassUtil.isBogusClass(serClass)) {
return null;
}
if (!JsonSerializer.class.isAssignableFrom(serClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "
+serClass.getName()+"; expected Class<JsonSerializer>");
}
HandlerInstantiator hi = _config.getHandlerInstantiator();
ser = (hi == null) ? null : hi.serializerInstance(_config, annotated, serClass);
if (ser == null) {
ser = (JsonSerializer<?>) ClassUtil.createInstance(serClass,
_config.canOverrideAccessModifiers());
}
}
return (JsonSerializer<Object>) _handleResolvable(ser);
}
/*
/**********************************************************
/* Helper classes
/**********************************************************
*/
/**
* Concrete implementation that defines factory method(s),
* defined as final.
*/
public final static class Impl extends DefaultSerializerProvider {
private static final long serialVersionUID = 1L;
public Impl() { super(); }
protected Impl(SerializerProvider src, SerializationConfig config
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> need to
* know creators.
*/
BeanDescription beanDesc = config.introspect(type);
// Ok, so: can we find T(String) constructor?
Constructor<?> ctor = beanDesc.findSingleArgConstructor(String.class);
if (ctor != null) {
if (config.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(ctor);
}
return new StdKeyDeserializer.StringCtorKeyDeserializer(ctor);
}
/* or if not, "static T valueOf(String)" (or equivalent marked
* with @JsonCreator annotation?)
*/
Method m = beanDesc.findFactoryMethod(String.class);
if (m != null){
if (config.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(m);
}
return new StdKeyDeserializer.StringFactoryKeyDeserializer(m);
}
// nope, no such luck...
return null;
}
/*
/**********************************************************
/* KeyDeserializers implementation
/**********************************************************
*/
@Override
public KeyDeserializer findKeyDeserializer(JavaType type,
DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException
{
Class<?> raw = type.getRawClass();
// 23-Apr-2013, tatu: Map primitive types, just in case one was given
if (raw.isPrimitive()) {
raw = ClassUtil.wrapperType(raw);
}
return StdKeyDeserializer.forType(raw);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.jsonFormatVisitors.*;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.util.StdDateFormat;
public abstract class DateTimeSerializerBase<T>
extends StdScalarSerializer<T>
implements ContextualSerializer
{
/**
* Flag that indicates that serialization must be done as the
* Java timestamp, regardless of other settings.
*/
protected final Boolean _useTimestamp;
/**
* Specific format to use, if not default format: non null value
* also indicates that serialization is to be done as JSON String,
* not numeric timestamp, unless {@link #_useTimestamp} is true.
*/
protected final DateFormat _customFormat;
protected DateTimeSerializerBase(Class<T> type,
Boolean useTimestamp, DateFormat customFormat)
{
super(type);
_useTimestamp = useTimestamp;
_customFormat = customFormat;
}
public abstract DateTimeSerializerBase<T> withFormat(Boolean timestamp, DateFormat customFormat);
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov,
BeanProperty property) throws JsonMappingException
{
if (property != null) {
JsonFormat.Value format = prov.getAnnotationIntrospector().findFormat((Annotated)property.getMember());
if (format != null) {
// Simple case first: serialize as numeric timestamp?
if (format.getShape().isNumeric()) {
return withFormat(Boolean.TRUE, null);
}
Boolean asNumber = (format.getShape() == JsonFormat.Shape.STRING) ? Boolean.FALSE : null;
// If not, do we
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> have a pattern?
TimeZone tz = format.getTimeZone();
if (format.hasPattern()) {
String pattern = format.getPattern();
final Locale loc = format.hasLocale() ? format.getLocale() : prov.getLocale();
SimpleDateFormat df = new SimpleDateFormat(pattern, loc);
if (tz == null) {
tz = prov.getTimeZone();
}
df.setTimeZone(tz);
return withFormat(asNumber, df);
}
// If not, do we at least have a custom timezone?
if (tz != null) {
DateFormat df = prov.getConfig().getDateFormat();
// one shortcut: with our custom format, can simplify handling a bit
if (df.getClass() == StdDateFormat.class) {
final Locale loc = format.hasLocale() ? format.getLocale() : prov.getLocale();
df = StdDateFormat.getISO8601Format(tz, loc);
} else {
// otherwise need to clone, re-set timezone:
df = (DateFormat) df.clone();
df.setTimeZone(tz);
}
return withFormat(asNumber, df);
}
}
}
return this;
}
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
@Override
public boolean isEmpty(T value) {
// let's assume "null date" (timestamp 0) qualifies for empty
return (value == null) || (_timestamp(value) == 0L);
}
protected abstract long _timestamp(T value);
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
//todo: (ryan) add a format for the date in the schema?
return createSchemaNode(_asTimestamp(provider) ? "number" : "string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
_acceptJsonFormatVisitor(visitor, typeHint, _asTimestamp(visitor.getProvider()));
}
/*
/**********************************************************
/* Actual serialization
/**********************************************************
*/
@Override
public abstract void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException;
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
protected
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> boolean _asTimestamp(SerializerProvider provider)
{
if (_useTimestamp != null) {
return _useTimestamp.booleanValue();
}
if (_customFormat == null) {
if (provider != null) {
return provider.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
// 12-Jun-2014, tatu: Is it legal not to have provider? Was NPE:ing earlier so leave a check
throw new IllegalArgumentException("Null 'provider' passed for "+handledType().getName());
}
return false;
}
protected void _acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint,
boolean asNumber) throws JsonMappingException
{
if (asNumber) {
JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
if (v2 != null) {
v2.numberType(JsonParser.NumberType.LONG);
v2.format(JsonValueFormat.UTC_MILLISEC);
}
} else {
JsonStringFormatVisitor v2 = visitor.expectStringFormat(typeHint);
if (v2 != null) {
v2.format(JsonValueFormat.DATE_TIME);
}
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> _method.getGenericReturnType();
}
/**
* For methods, this returns declared return type, which is only
* useful with getters (setters do not usually return anything;
* hence "void" type is returned here)
*/
@Override
public Class<?> getRawType() {
return _method.getReturnType();
}
/**
* As per [JACKSON-468], we need to also allow declaration of local
* type bindings; mostly it will allow defining bounds.
*/
@Override
public JavaType getType(TypeBindings bindings) {
return getType(bindings, _method.getTypeParameters());
}
@Override
public final Object call() throws Exception {
return _method.invoke(null);
}
@Override
public final Object call(Object[] args) throws Exception {
return _method.invoke(null, args);
}
@Override
public final Object call1(Object arg) throws Exception {
return _method.invoke(null, arg);
}
/*
/********************************************************
/* AnnotatedMember impl
/********************************************************
*/
@Override
public Class<?> getDeclaringClass() { return _method.getDeclaringClass(); }
@Override
public Method getMember() { return _method; }
@Override
public void setValue(Object pojo, Object value)
throws IllegalArgumentException
{
try {
_method.invoke(pojo, value);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Failed to setValue() with method "
+getFullName()+": "+e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new IllegalArgumentException("Failed to setValue() with method "
+getFullName()+": "+e.getMessage(), e);
}
}
@Override
public Object getValue(Object pojo) throws IllegalArgumentException
{
try {
return _method.invoke(pojo);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Failed to getValue() with method "
+getFullName()+": "+e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new IllegalArgumentException("Failed to getValue() with method "
+getFullName()+": "+e.getMessage(), e);
}
}
/*
/*****************************************************
/* Extended API, generic
/*****************************************************
*/
@Override
public int getParameterCount() {
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> return getRawParameterTypes().length;
}
public String getFullName() {
return getDeclaringClass().getName() + "#" + getName() + "("
+getParameterCount()+" params)";
}
public Class<?>[] getRawParameterTypes()
{
if (_paramClasses == null) {
_paramClasses = _method.getParameterTypes();
}
return _paramClasses;
}
public Type[] getGenericParameterTypes() {
return _method.getGenericParameterTypes();
}
@Override
public Class<?> getRawParameterType(int index)
{
Class<?>[] types = getRawParameterTypes();
return (index >= types.length) ? null : types[index];
}
@Override
public Type getGenericParameterType(int index)
{
Type[] types = _method.getGenericParameterTypes();
return (index >= types.length) ? null : types[index];
}
public Class<?> getRawReturnType() {
return _method.getReturnType();
}
public Type getGenericReturnType() {
return _method.getGenericReturnType();
}
/**
* Helper method that can be used to check whether method returns
* a value or not; if return type declared as <code>void</code>, returns
* false, otherwise true
*
* @since 2.4
*/
public boolean hasReturnType() {
Class<?> rt = getRawReturnType();
return (rt != Void.TYPE && rt != Void.class);
}
/*
/********************************************************
/* Other
/********************************************************
*/
@Override
public String toString()
{
return "[method "+getFullName()+"]";
}
/*
/**********************************************************
/* JDK serialization handling
/**********************************************************
*/
Object writeReplace() {
return new AnnotatedMethod(new Serialization(_method));
}
Object readResolve() {
Class<?> clazz = _serialization.clazz;
try {
Method m = clazz.getDeclaredMethod(_serialization.name,
_serialization.args);
// 06-Oct-2012, tatu: Has "lost" its security override, may need to force back
if (!m.isAccessible()) {
ClassUtil.checkAndFixAccess(m);
}
return new AnnotatedMethod(m, null, null);
} catch (Exception e) {
throw new IllegalArgumentException("Could
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.util.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
/**
* Standard deserializer for {@link EnumSet}s.
* <p>
* Note: casting within this class is all messed up -- just could not figure out a way
* to properly deal with recursive definition of "EnumSet<K extends Enum<K>, V>
*/
@SuppressWarnings("rawtypes")
public class EnumSetDeserializer
extends StdDeserializer<EnumSet<?>>
implements ContextualDeserializer
{
private static final long serialVersionUID = 3479455075597887177L;
protected final JavaType _enumType;
protected final Class<Enum> _enumClass;
protected JsonDeserializer<Enum<?>> _enumDeserializer;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
@SuppressWarnings("unchecked" )
public EnumSetDeserializer(JavaType enumType, JsonDeserializer<?> deser)
{
super(EnumSet.class);
_enumType = enumType;
_enumClass = (Class<Enum>) enumType.getRawClass();
_enumDeserializer = (JsonDeserializer<Enum<?>>) deser;
}
public EnumSetDeserializer withDeserializer(JsonDeserializer<?> deser) {
if (_enumDeserializer == deser) {
return this;
}
return new EnumSetDeserializer(_enumType, deser);
}
/**
* Because of costs associated with constructing Enum resolvers,
* let's cache instances by default.
*/
@Override
public boolean isCachable() { return true; }
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonDeserializer<?> deser = _enumDeserializer;
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(_enumType, property);
} else { // if directly assigned, probably not yet contextual, so:
deser = ctxt.handleSecondaryContextualization(deser, property);
}
return withDeserializer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(deser);
}
/*
/**********************************************************
/* JsonDeserializer API
/**********************************************************
*/
@SuppressWarnings("unchecked")
@Override
public EnumSet<?> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
throw ctxt.mappingException(EnumSet.class);
}
EnumSet result = constructSet();
JsonToken t;
try {
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
/* What to do with nulls? Fail or ignore? Fail, for now
* (note: would fail if we passed it to EnumDeserializer, too,
* but in general nulls should never be passed to non-container
* deserializers)
*/
if (t == JsonToken.VALUE_NULL) {
throw ctxt.mappingException(_enumClass);
}
Enum<?> value = _enumDeserializer.deserialize(jp, ctxt);
/* 24-Mar-2012, tatu: As per [JACKSON-810], may actually get nulls;
* but EnumSets don't allow nulls so need to skip.
*/
if (value != null) {
result.add(value);
}
}
} catch (Exception e) {
// note: pass Object.class, not Object[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, Enum.class, result.size());
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
@SuppressWarnings("unchecked")
private EnumSet constructSet()
{
// superbly ugly... but apparently necessary
return EnumSet.noneOf(_enumClass);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* Serializer used for primitive boolean, as well as java.util.Boolean
* wrapper type.
*<p>
* Since this is one of "native" types, no type information is ever
* included on serialization (unlike for most scalar types as of 1.5)
*/
@JacksonStdImpl
public final class BooleanSerializer
extends NonTypedScalarSerializerBase<Boolean>
{
/**
* Whether type serialized is primitive (boolean) or wrapper
* (java.lang.Boolean); if true, former, if false, latter.
*/
protected final boolean _forPrimitive;
public BooleanSerializer(boolean forPrimitive) {
super(Boolean.class);
_forPrimitive = forPrimitive;
}
@Override
public void serialize(Boolean value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
jgen.writeBoolean(value.booleanValue());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("boolean", !_forPrimitive);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
if (visitor != null) {
visitor.expectBooleanFormat(typeHint);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> shared (slow) cache
/**********************************************************
*/
public synchronized int size() {
return _sharedMap.size();
}
/**
* Method that checks if the shared (and hence, synchronized) lookup Map might have
* untyped serializer for given type.
*/
public JsonSerializer<Object> untypedValueSerializer(Class<?> type)
{
synchronized (this) {
return _sharedMap.get(new TypeKey(type, false));
}
}
public JsonSerializer<Object> untypedValueSerializer(JavaType type)
{
synchronized (this) {
return _sharedMap.get(new TypeKey(type, false));
}
}
public JsonSerializer<Object> typedValueSerializer(JavaType type)
{
synchronized (this) {
return _sharedMap.get(new TypeKey(type, true));
}
}
public JsonSerializer<Object> typedValueSerializer(Class<?> cls)
{
synchronized (this) {
return _sharedMap.get(new TypeKey(cls, true));
}
}
/*
/**********************************************************
/* Methods for adding shared serializer instances
/**********************************************************
*/
/**
* Method called if none of lookups succeeded, and caller had to construct
* a serializer. If so, we will update the shared lookup map so that it
* can be resolved via it next time.
*/
public void addTypedSerializer(JavaType type, JsonSerializer<Object> ser)
{
synchronized (this) {
if (_sharedMap.put(new TypeKey(type, true), ser) == null) {
// let's invalidate the read-only copy, too, to get it updated
_readOnlyMap = null;
}
}
}
public void addTypedSerializer(Class<?> cls, JsonSerializer<Object> ser)
{
synchronized (this) {
if (_sharedMap.put(new TypeKey(cls, true), ser) == null) {
// let's invalidate the read-only copy, too, to get it updated
_readOnlyMap = null;
}
}
}
public void addAndResolveNonTypedSerializer(Class<?> type, JsonSerializer<Object> ser,
SerializerProvider provider)
throws JsonMappingException
{
synchronized (this) {
if (_sharedMap.put(new TypeKey(type, false), ser) == null
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>) {
// let's invalidate the read-only copy, too, to get it updated
_readOnlyMap = null;
}
/* Finally: some serializers want to do post-processing, after
* getting registered (to handle cyclic deps).
*/
/* 14-May-2011, tatu: As per [JACKSON-570], resolving needs to be done
* in synchronized manner; this because while we do need to register
* instance first, we also must keep lock until resolution is complete
*/
if (ser instanceof ResolvableSerializer) {
((ResolvableSerializer) ser).resolve(provider);
}
}
}
public void addAndResolveNonTypedSerializer(JavaType type, JsonSerializer<Object> ser,
SerializerProvider provider)
throws JsonMappingException
{
synchronized (this) {
if (_sharedMap.put(new TypeKey(type, false), ser) == null) {
// let's invalidate the read-only copy, too, to get it updated
_readOnlyMap = null;
}
/* Finally: some serializers want to do post-processing, after
* getting registered (to handle cyclic deps).
*/
/* 14-May-2011, tatu: As per [JACKSON-570], resolving needs to be done
* in synchronized manner; this because while we do need to register
* instance first, we also must keep lock until resolution is complete
*/
if (ser instanceof ResolvableSerializer) {
((ResolvableSerializer) ser).resolve(provider);
}
}
}
/**
* Method called by StdSerializerProvider#flushCachedSerializers() to
* clear all cached serializers
*/
public synchronized void flush() {
_sharedMap.clear();
}
/*
/**************************************************************
/* Helper class(es)
/**************************************************************
*/
/**
* Key that offers two "modes"; one with raw class, as used for
* cases were raw class type is available (for example, when using
* runtime type); and one with full generics-including.
*/
public final static class TypeKey
{
protected int _hashCode;
protected Class<?> _class;
protected JavaType _type;
/**
* Indicator of whether serializer stored has a type serializer
* wrapper around it
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>);
/**
* Convenience method for creating a new factory instance with an additional
* serializer provider.
*/
@Override
public final SerializerFactory withAdditionalSerializers(Serializers additional) {
return withConfig(_factoryConfig.withAdditionalSerializers(additional));
}
/**
* Convenience method for creating a new factory instance with an additional
* key serializer provider.
*/
@Override
public final SerializerFactory withAdditionalKeySerializers(Serializers additional) {
return withConfig(_factoryConfig.withAdditionalKeySerializers(additional));
}
/**
* Convenience method for creating a new factory instance with additional bean
* serializer modifier.
*/
@Override
public final SerializerFactory withSerializerModifier(BeanSerializerModifier modifier) {
return withConfig(_factoryConfig.withSerializerModifier(modifier));
}
/*
/**********************************************************
/* SerializerFactory impl
/**********************************************************
*/
// Implemented by sub-classes
@Override
public abstract JsonSerializer<Object> createSerializer(SerializerProvider prov,
JavaType type)
throws JsonMappingException;
@Override
@SuppressWarnings("unchecked")
public JsonSerializer<Object> createKeySerializer(SerializationConfig config,
JavaType keyType, JsonSerializer<Object> defaultImpl)
{
// We should not need any member method info; at most class annotations for Map type
BeanDescription beanDesc = config.introspectClassAnnotations(keyType.getRawClass());
JsonSerializer<?> ser = null;
// Minor optimization: to avoid constructing beanDesc, bail out if none registered
if (_factoryConfig.hasKeySerializers()) {
// Only thing we have here are module-provided key serializers:
for (Serializers serializers : _factoryConfig.keySerializers()) {
ser = serializers.findSerializer(config, keyType, beanDesc);
if (ser != null) {
break;
}
}
}
if (ser == null) {
ser = defaultImpl;
if (ser == null) {
ser = StdKeySerializers.getStdKeySerializer(keyType);
}
}
// [Issue#120]: Allow post-processing
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
ser = mod.modifyKeySerializer(config, keyType, beanDesc, ser);
}
}
return (JsonSerializer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS><Object>) ser;
}
/**
* Method called to construct a type serializer for values with given declared
* base type. This is called for values other than those of bean property
* types.
*/
@Override
public TypeSerializer createTypeSerializer(SerializationConfig config,
JavaType baseType)
{
BeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass());
AnnotatedClass ac = bean.getClassInfo();
AnnotationIntrospector ai = config.getAnnotationIntrospector();
TypeResolverBuilder<?> b = ai.findTypeResolver(config, ac, baseType);
/* Ok: if there is no explicit type info handler, we may want to
* use a default. If so, config object knows what to use.
*/
Collection<NamedType> subtypes = null;
if (b == null) {
b = config.getDefaultTyper(baseType);
} else {
subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai);
}
if (b == null) {
return null;
}
return b.buildTypeSerializer(config, baseType, subtypes);
}
/*
/**********************************************************
/* Additional API for other core classes
/**********************************************************
*/
protected abstract Iterable<Serializers> customSerializers();
/*
/**********************************************************
/* Overridable secondary serializer accessor methods
/**********************************************************
*/
/**
* Method that will use fast lookup (and identity comparison) methods to
* see if we know serializer to use for given type.
*/
protected final JsonSerializer<?> findSerializerByLookup(JavaType type,
SerializationConfig config, BeanDescription beanDesc,
boolean staticTyping)
{
Class<?> raw = type.getRawClass();
String clsName = raw.getName();
JsonSerializer<?> ser = _concrete.get(clsName);
if (ser == null) {
Class<? extends JsonSerializer<?>> serClass = _concreteLazy.get(clsName);
if (serClass != null) {
try {
return serClass.newInstance();
} catch (Exception e) {
throw new IllegalStateException("Failed to instantiate standard serializer (of type "+serClass.getName()+"): "
+e.getMessage(), e);
}
}
}
return ser;
}
/**
* Method called to see if one
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> of primary per-class annotations
* (or related, like implementing of {@link JsonSerializable})
* determines the serializer to use.
*<p>
* Currently handles things like:
*<ul>
* <li>If type implements {@link JsonSerializable}, use that
* </li>
* <li>If type has {@link com.fasterxml.jackson.annotation.JsonValue} annotation (or equivalent), build serializer
* based on that property
* </li>
*</ul>
*
* @since 2.0
*/
protected final JsonSerializer<?> findSerializerByAnnotations(SerializerProvider prov,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
Class<?> raw = type.getRawClass();
// First: JsonSerializable?
if (JsonSerializable.class.isAssignableFrom(raw)) {
return SerializableSerializer.instance;
}
// Second: @JsonValue for any type
AnnotatedMethod valueMethod = beanDesc.findJsonValueMethod();
if (valueMethod != null) {
Method m = valueMethod.getAnnotated();
if (prov.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(m);
}
JsonSerializer<Object> ser = findSerializerFromAnnotation(prov, valueMethod);
return new JsonValueSerializer(m, ser);
}
// No well-known annotations...
return null;
}
/**
* Method for checking if we can determine serializer to use based on set of
* known primary types, checking for set of known base types (exact matches
* having been compared against with <code>findSerializerByLookup</code>).
* This does not include "secondary" interfaces, but
* mostly concrete or abstract base classes.
*/
protected final JsonSerializer<?> findSerializerByPrimaryType(SerializerProvider prov,
JavaType type, BeanDescription beanDesc,
boolean staticTyping)
throws JsonMappingException
{
Class<?> raw = type.getRawClass();
// Then check for optional/external serializers [JACKSON-386]
JsonSerializer<?> ser = findOptionalStdSerializer(prov, type, beanDesc, staticTyping);
if (ser != null) {
return ser;
}
if (Calendar.class.isAssignableFrom(raw)) {
return CalendarSerializer.instance;
}
if (java.util.Date.class.isAssignableFrom(
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>raw)) {
return DateSerializer.instance;
}
if (ByteBuffer.class.isAssignableFrom(raw)) {
return new ByteBufferSerializer();
}
if (InetAddress.class.isAssignableFrom(raw)) {
return new InetAddressSerializer();
}
if (InetSocketAddress.class.isAssignableFrom(raw)) {
return new InetSocketAddressSerializer();
}
if (TimeZone.class.isAssignableFrom(raw)) {
return new TimeZoneSerializer();
}
if (java.nio.charset.Charset.class.isAssignableFrom(raw)) {
return ToStringSerializer.instance;
}
if (Number.class.isAssignableFrom(raw)) {
// 21-May-2014, tatu: Couple of alternatives actually
JsonFormat.Value format = beanDesc.findExpectedFormat(null);
if (format != null) {
switch (format.getShape()) {
case STRING:
return ToStringSerializer.instance;
case OBJECT: // need to bail out to let it be serialized as POJO
case ARRAY: // or, I guess ARRAY; otherwise no point in speculating
return null;
default:
}
}
return NumberSerializer.instance;
}
if (Enum.class.isAssignableFrom(raw)) {
return buildEnumSerializer(prov.getConfig(), type, beanDesc);
}
return null;
}
/**
* Overridable method called after checking all other types.
*
* @since 2.2
*/
protected JsonSerializer<?> findOptionalStdSerializer(SerializerProvider prov,
JavaType type, BeanDescription beanDesc, boolean staticTyping)
throws JsonMappingException
{
return OptionalHandlerFactory.instance.findSerializer(prov.getConfig(), type, beanDesc);
}
/**
* Reflection-based serialized find method, which checks if
* given class implements one of recognized "add-on" interfaces.
* Add-on here means a role that is usually or can be a secondary
* trait: for example,
* bean classes may implement {@link Iterable}, but their main
* function is usually something else. The reason for
*/
protected final JsonSerializer<?> findSerializerByAddonType(SerializationConfig config,
JavaType javaType, BeanDescription beanDesc, boolean staticTyping) throws JsonMappingException
{
Class<?> type = javaType.getRawClass();
// These need to be in decreasing order
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> of specificity...
if (Iterator.class.isAssignableFrom(type)) {
return buildIteratorSerializer(config, javaType, beanDesc, staticTyping);
}
if (Iterable.class.isAssignableFrom(type)) {
return buildIterableSerializer(config, javaType, beanDesc, staticTyping);
}
if (CharSequence.class.isAssignableFrom(type)) {
return ToStringSerializer.instance;
}
return null;
}
/**
* Helper method called to check if a class or method
* has an annotation
* (@link com.fasterxml.jackson.databind.annotation.JsonSerialize#using)
* that tells the class to use for serialization.
* Returns null if no such annotation found.
*/
@SuppressWarnings("unchecked")
protected JsonSerializer<Object> findSerializerFromAnnotation(SerializerProvider prov,
Annotated a)
throws JsonMappingException
{
Object serDef = prov.getAnnotationIntrospector().findSerializer(a);
if (serDef == null) {
return null;
}
JsonSerializer<Object> ser = prov.serializerInstance(a, serDef);
// One more thing however: may need to also apply a converter:
return (JsonSerializer<Object>) findConvertingSerializer(prov, a, ser);
}
/**
* Helper method that will check whether given annotated entity (usually class,
* but may also be a property accessor) indicates that a {@link Converter} is to
* be used; and if so, to construct and return suitable serializer for it.
* If not, will simply return given serializer as is.
*/
protected JsonSerializer<?> findConvertingSerializer(SerializerProvider prov,
Annotated a, JsonSerializer<?> ser)
throws JsonMappingException
{
Converter<Object,Object> conv = findConverter(prov, a);
if (conv == null) {
return ser;
}
JavaType delegateType = conv.getOutputType(prov.getTypeFactory());
return new StdDelegatingSerializer(conv, delegateType, ser);
}
protected Converter<Object,Object> findConverter(SerializerProvider prov,
Annotated a)
throws JsonMappingException
{
Object convDef = prov.getAnnotationIntrospector().findSerializationConverter(a);
if (convDef == null) {
return null;
}
return prov.converterInstance(a, convDef);
}
/*
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
/**********************************************************
/* Factory methods, container types:
/**********************************************************
*/
/**
* @since 2.1
*/
protected JsonSerializer<?> buildContainerSerializer(SerializerProvider prov,
JavaType type, BeanDescription beanDesc, boolean staticTyping)
throws JsonMappingException
{
final SerializationConfig config = prov.getConfig();
/* [Issue#23], 15-Mar-2013, tatu: must force static handling of root value type,
* with just one important exception: if value type is "untyped", let's
* leave it as is; no clean way to make it work.
*/
if (!staticTyping && type.useStaticType()) {
if (!type.isContainerType() || type.getContentType().getRawClass() != Object.class) {
staticTyping = true;
}
}
// Let's see what we can learn about element/content/value type, type serializer for it:
JavaType elementType = type.getContentType();
TypeSerializer elementTypeSerializer = createTypeSerializer(config,
elementType);
// if elements have type serializer, can not force static typing:
if (elementTypeSerializer != null) {
staticTyping = false;
}
JsonSerializer<Object> elementValueSerializer = _findContentSerializer(prov,
beanDesc.getClassInfo());
if (type.isMapLikeType()) { // implements java.util.Map
MapLikeType mlt = (MapLikeType) type;
/* 29-Sep-2012, tatu: This is actually too early to (try to) find
* key serializer from property annotations, and can lead to caching
* issues (see [Issue#75]). Instead, must be done from 'createContextual()' call.
* But we do need to check class annotations.
*/
JsonSerializer<Object> keySerializer = _findKeySerializer(prov, beanDesc.getClassInfo());
if (mlt.isTrueMapType()) {
return buildMapSerializer(config, (MapType) mlt, beanDesc, staticTyping,
keySerializer, elementTypeSerializer, elementValueSerializer);
}
// Only custom serializers may be available:
for (Serializers serializers : customSerializers()) {
MapLikeType mlType = (MapLikeType) type;
JsonSerializer<?>
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> ser = serializers.findMapLikeSerializer(config,
mlType, beanDesc, keySerializer, elementTypeSerializer, elementValueSerializer);
if (ser != null) {
// [Issue#120]: Allow post-processing
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
ser = mod.modifyMapLikeSerializer(config, mlType, beanDesc, ser);
}
}
return ser;
}
}
return null;
}
if (type.isCollectionLikeType()) {
CollectionLikeType clt = (CollectionLikeType) type;
if (clt.isTrueCollectionType()) {
return buildCollectionSerializer(config, (CollectionType) clt, beanDesc, staticTyping,
elementTypeSerializer, elementValueSerializer);
}
CollectionLikeType clType = (CollectionLikeType) type;
// Only custom variants for this:
for (Serializers serializers : customSerializers()) {
JsonSerializer<?> ser = serializers.findCollectionLikeSerializer(config,
clType, beanDesc, elementTypeSerializer, elementValueSerializer);
if (ser != null) {
// [Issue#120]: Allow post-processing
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
ser = mod.modifyCollectionLikeSerializer(config, clType, beanDesc, ser);
}
}
return ser;
}
}
// fall through either way (whether shape dictates serialization as POJO or not)
return null;
}
if (type.isArrayType()) {
return buildArraySerializer(config, (ArrayType) type, beanDesc, staticTyping,
elementTypeSerializer, elementValueSerializer);
}
return null;
}
/**
* Helper method that handles configuration details when constructing serializers for
* {@link java.util.List} types that support efficient by-index access
*
* @since 2.1
*/
protected JsonSerializer<?> buildCollectionSerializer(SerializationConfig config,
CollectionType type, BeanDescription beanDesc, boolean staticTyping,
TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer)
throws JsonMappingException
{
JsonSerializer<?> ser = null;
// Module-provided custom collection serializers?
for (Serial
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> ser = mod.modifyCollectionSerializer(config, type, beanDesc, ser);
}
}
return ser;
}
/*
/**********************************************************
/* Factory methods, for Collections
/**********************************************************
*/
protected boolean isIndexedList(Class<?> cls)
{
return RandomAccess.class.isAssignableFrom(cls);
}
public ContainerSerializer<?> buildIndexedListSerializer(JavaType elemType,
boolean staticTyping, TypeSerializer vts, JsonSerializer<Object> valueSerializer) {
return new IndexedListSerializer(elemType, staticTyping, vts, null, valueSerializer);
}
public ContainerSerializer<?> buildCollectionSerializer(JavaType elemType,
boolean staticTyping, TypeSerializer vts, JsonSerializer<Object> valueSerializer) {
return new CollectionSerializer(elemType, staticTyping, vts, null, valueSerializer);
}
public JsonSerializer<?> buildEnumSetSerializer(JavaType enumType) {
return new EnumSetSerializer(enumType, null);
}
/*
/**********************************************************
/* Factory methods, for Maps
/**********************************************************
*/
/**
* Helper method that handles configuration details when constructing serializers for
* {@link java.util.Map} types.
*/
protected JsonSerializer<?> buildMapSerializer(SerializationConfig config,
MapType type, BeanDescription beanDesc,
boolean staticTyping, JsonSerializer<Object> keySerializer,
TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer)
throws JsonMappingException
{
JsonSerializer<?> ser = null;
for (Serializers serializers : customSerializers()) {
ser = serializers.findMapSerializer(config, type, beanDesc,
keySerializer, elementTypeSerializer, elementValueSerializer);
if (ser != null) { break; }
}
if (ser == null) {
if (EnumMap.class.isAssignableFrom(type.getRawClass())) {
JavaType keyType = type.getKeyType();
// Need to find key enum values...
EnumValues enums = null;
if (keyType.isEnumType()) { // non-enum if we got it as type erased class (from instance)
@SuppressWarnings("unchecked")
Class<Enum<?>> enumClass = (Class<Enum<?>>) keyType.getRawClass();
enums = EnumValues.construct(config, enumClass);
}
ser = new EnumMapSerializer(type.getContentType(), static
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Typing, enums,
elementTypeSerializer, elementValueSerializer);
} else {
Object filterId = findFilterId(config, beanDesc);
ser = MapSerializer.construct(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()),
type, staticTyping, elementTypeSerializer,
keySerializer, elementValueSerializer, filterId);
}
}
// [Issue#120]: Allow post-processing
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
ser = mod.modifyMapSerializer(config, type, beanDesc, ser);
}
}
return ser;
}
/*
/**********************************************************
/* Factory methods, for Arrays
/**********************************************************
*/
/**
* Helper method that handles configuration details when constructing serializers for
* <code>Object[]</code> (and subtypes, except for String).
*/
protected JsonSerializer<?> buildArraySerializer(SerializationConfig config,
ArrayType type, BeanDescription beanDesc,
boolean staticTyping,
TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer)
throws JsonMappingException
{
JsonSerializer<?> ser = null;
// Module-provided custom collection serializers?
for (Serializers serializers : customSerializers()) {
ser = serializers.findArraySerializer(config,
type, beanDesc, elementTypeSerializer, elementValueSerializer);
if (ser != null) {
break;
}
}
if (ser == null) {
Class<?> raw = type.getRawClass();
// Important: do NOT use standard serializers if non-standard element value serializer specified
if (elementValueSerializer == null || ClassUtil.isJacksonStdImpl(elementValueSerializer)) {
if (String[].class == raw) {
ser = StringArraySerializer.instance;
} else {
// other standard types?
ser = StdArraySerializers.findStandardImpl(raw);
}
}
if (ser == null) {
ser = new ObjectArraySerializer(type.getContentType(), staticTyping, elementTypeSerializer,
elementValueSerializer);
}
}
// [Issue#120]: Allow post-processing
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
ser = mod
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.modifyArraySerializer(config, type, beanDesc, ser);
}
}
return ser;
}
/*
/**********************************************************
/* Factory methods, for non-container types
/**********************************************************
*/
protected JsonSerializer<?> buildIteratorSerializer(SerializationConfig config,
JavaType type, BeanDescription beanDesc,
boolean staticTyping)
throws JsonMappingException
{
// if there's generic type, it'll be the first contained type
JavaType valueType = type.containedType(0);
if (valueType == null) {
valueType = TypeFactory.unknownType();
}
TypeSerializer vts = createTypeSerializer(config, valueType);
return new IteratorSerializer(valueType, staticTyping, vts, null);
}
protected JsonSerializer<?> buildIterableSerializer(SerializationConfig config,
JavaType type, BeanDescription beanDesc,
boolean staticTyping)
throws JsonMappingException
{
// if there's generic type, it'll be the first contained type
JavaType valueType = type.containedType(0);
if (valueType == null) {
valueType = TypeFactory.unknownType();
}
TypeSerializer vts = createTypeSerializer(config, valueType);
return new IterableSerializer(valueType, staticTyping, vts, null);
}
protected JsonSerializer<?> buildEnumSerializer(SerializationConfig config,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
/* As per [Issue#24], may want to use alternate shape, serialize as JSON Object.
* Challenge here is that EnumSerializer does not know how to produce
* POJO style serialization, so we must handle that special case separately;
* otherwise pass it to EnumSerializer.
*/
JsonFormat.Value format = beanDesc.findExpectedFormat(null);
if (format != null && format.getShape() == JsonFormat.Shape.OBJECT) {
// one special case: suppress serialization of "getDeclaringClass()"...
((BasicBeanDescription) beanDesc).removeProperty("declaringClass");
// returning null will mean that eventually BeanSerializer gets constructed
return null;
}
@SuppressWarnings("unchecked")
Class<Enum<?>> enumClass = (Class<Enum<?>>) type.getRawClass();
JsonSerializer<?> ser = EnumSerializer.construct(enumClass, config, beanDesc, format);
// [Issue#120]:
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>widenContentsBy(cc);
} catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("Failed to narrow content type "+type+" with content-type annotation ("+cc.getName()+"): "+iae.getMessage());
}
}
}
return type;
}
/**
* Helper method called to try to find whether there is an annotation in the
* class that indicates key serializer to use.
* If so, will try to instantiate key serializer and return it; otherwise returns null.
*/
protected JsonSerializer<Object> _findKeySerializer(SerializerProvider prov,
Annotated a)
throws JsonMappingException
{
AnnotationIntrospector intr = prov.getAnnotationIntrospector();
Object serDef = intr.findKeySerializer(a);
if (serDef != null) {
return prov.serializerInstance(a, serDef);
}
return null;
}
/**
* Helper method called to try to find whether there is an annotation in the
* class that indicates content ("value") serializer to use.
* If so, will try to instantiate key serializer and return it; otherwise returns null.
*/
protected JsonSerializer<Object> _findContentSerializer(SerializerProvider prov,
Annotated a)
throws JsonMappingException
{
AnnotationIntrospector intr = prov.getAnnotationIntrospector();
Object serDef = intr.findContentSerializer(a);
if (serDef != null) {
return prov.serializerInstance(a, serDef);
}
return null;
}
/**
* Method called to find filter that is configured to be used with bean
* serializer being built, if any.
*/
protected Object findFilterId(SerializationConfig config, BeanDescription beanDesc) {
return config.getAnnotationIntrospector().findFilterId((Annotated)beanDesc.getClassInfo());
}
/**
* Helper method to check whether global settings and/or class
* annotations for the bean class indicate that static typing
* (declared types) should be used for properties.
* (instead of dynamic runtime types).
*
* @since 2.1 (earlier had variant with additional 'property' parameter)
*/
protected boolean usesStaticTyping(SerializationConfig config,
BeanDescription beanDesc, TypeSerializer typeSer)
{
/* 16-Aug-2010, tatu: If there is
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser;
import com.fasterxml.jackson.databind.*;
/**
* Interface that defines API for simple extensions that can provide additional deserializers
* for deserializer Map keys of various types, from JSON property names.
* Access is by a single callback method; instance is to either return
* a configured {@link KeyDeserializer} for specified type, or null to indicate that it
* does not support handling of the type. In latter case, further calls can be made
* for other providers; in former case returned key deserializer is used for handling of
* key instances of specified type.
*/
public interface KeyDeserializers
{
public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> * 'setter' method signature and/or type annotations
*
* @throws JsonMappingException if there are fatal problems with
* accessing suitable deserializer; including that of not
* finding any serializer
*/
public JsonDeserializer<Object> findValueDeserializer(DeserializationContext ctxt,
DeserializerFactory factory, JavaType propertyType)
throws JsonMappingException
{
JsonDeserializer<Object> deser = _findCachedDeserializer(propertyType);
if (deser == null) {
// If not, need to request factory to construct (or recycle)
deser = _createAndCacheValueDeserializer(ctxt, factory, propertyType);
if (deser == null) {
/* Should we let caller handle it? Let's have a helper method
* decide it; can throw an exception, or return a valid
* deserializer
*/
deser = _handleUnknownValueDeserializer(propertyType);
}
}
return deser;
}
/**
* Method called to get hold of a deserializer to use for deserializing
* keys for {@link java.util.Map}.
*
* @throws JsonMappingException if there are fatal problems with
* accessing suitable key deserializer; including that of not
* finding any serializer
*/
public KeyDeserializer findKeyDeserializer(DeserializationContext ctxt,
DeserializerFactory factory, JavaType type)
throws JsonMappingException
{
KeyDeserializer kd = factory.createKeyDeserializer(ctxt, type);
if (kd == null) { // if none found, need to use a placeholder that'll fail
return _handleUnknownKeyDeserializer(type);
}
// First: need to resolve?
if (kd instanceof ResolvableDeserializer) {
((ResolvableDeserializer) kd).resolve(ctxt);
}
return kd;
}
/**
* Method called to find out whether provider would be able to find
* a deserializer for given type, using a root reference (i.e. not
* through fields or membership in an array or collection)
*/
public boolean hasValueDeserializerFor(DeserializationContext ctxt,
DeserializerFactory factory, JavaType type)
throws JsonMappingException
{
/* Note: mostly copied from findValueDeserializer, except for
* handling of unknown types
*/
JsonDeserializer<Object> deser = _findCachedDeserializer(type);
if (deser == null
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>) {
deser = _createAndCacheValueDeserializer(ctxt, factory, type);
}
return (deser != null);
}
/*
/**********************************************************
/* Helper methods that handle cache lookups
/**********************************************************
*/
protected JsonDeserializer<Object> _findCachedDeserializer(JavaType type)
{
if (type == null) {
throw new IllegalArgumentException("Null JavaType passed");
}
return _cachedDeserializers.get(type);
}
/**
* Method that will try to create a deserializer for given type,
* and resolve and cache it if necessary
*
* @param ctxt Currently active deserialization context
* @param type Type of property to deserialize
*/
protected JsonDeserializer<Object>_createAndCacheValueDeserializer(DeserializationContext ctxt,
DeserializerFactory factory, JavaType type)
throws JsonMappingException
{
/* Only one thread to construct deserializers at any given point in time;
* limitations necessary to ensure that only completely initialized ones
* are visible and used.
*/
synchronized (_incompleteDeserializers) {
// Ok, then: could it be that due to a race condition, deserializer can now be found?
JsonDeserializer<Object> deser = _findCachedDeserializer(type);
if (deser != null) {
return deser;
}
int count = _incompleteDeserializers.size();
// Or perhaps being resolved right now?
if (count > 0) {
deser = _incompleteDeserializers.get(type);
if (deser != null) {
return deser;
}
}
// Nope: need to create and possibly cache
try {
return _createAndCache2(ctxt, factory, type);
} finally {
// also: any deserializers that have been created are complete by now
if (count == 0 && _incompleteDeserializers.size() > 0) {
_incompleteDeserializers.clear();
}
}
}
}
/**
* Method that handles actual construction (via factory) and caching (both
* intermediate and eventual)
*/
protected JsonDeserializer<Object> _createAndCache2(DeserializationContext ctxt,
DeserializerFactory factory, JavaType type)
throws JsonMappingException
{
JsonDeserializer<Object> deser;
try {
deser = _createDeserializer(ctxt,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> factory, type);
} catch (IllegalArgumentException iae) {
/* We better only expose checked exceptions, since those
* are what caller is expected to handle
*/
throw new JsonMappingException(iae.getMessage(), null, iae);
}
if (deser == null) {
return null;
}
/* cache resulting deserializer? always true for "plain" BeanDeserializer
* (but can be re-defined for sub-classes by using @JsonCachable!)
*/
// 08-Jun-2010, tatu: Related to [JACKSON-296], need to avoid caching MapSerializers... so:
boolean isResolvable = (deser instanceof ResolvableDeserializer);
boolean addToCache = deser.isCachable();
/* we will temporarily hold on to all created deserializers (to
* handle cyclic references, and possibly reuse non-cached
* deserializers (list, map))
*/
/* 07-Jun-2010, tatu: Danger: [JACKSON-296] was caused by accidental
* resolution of a reference -- couple of ways to prevent this;
* either not add Lists or Maps, or clear references eagerly.
* Let's actually do both; since both seem reasonable.
*/
/* Need to resolve? Mostly done for bean deserializers; required for
* resolving cyclic references.
*/
if (isResolvable) {
_incompleteDeserializers.put(type, deser);
((ResolvableDeserializer)deser).resolve(ctxt);
_incompleteDeserializers.remove(type);
}
if (addToCache) {
_cachedDeserializers.put(type, deser);
}
return deser;
}
/*
/**********************************************************
/* Helper methods for actual construction of deserializers
/**********************************************************
*/
/**
* Method that does the heavy lifting of checking for per-type annotations,
* find out full type, and figure out which actual factory method
* to call.
*/
@SuppressWarnings("unchecked")
protected JsonDeserializer<Object> _createDeserializer(DeserializationContext ctxt,
DeserializerFactory factory, JavaType type)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
// First things first: do we need to use
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> abstract type mapping?
if (type.isAbstract() || type.isMapLikeType() || type.isCollectionLikeType()) {
type = factory.mapAbstractType(config, type);
}
BeanDescription beanDesc = config.introspect(type);
// Then: does type define explicit deserializer to use, with annotation(s)?
JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt,
beanDesc.getClassInfo());
if (deser != null) {
return deser;
}
// If not, may have further type-modification annotations to check:
JavaType newType = modifyTypeByAnnotation(ctxt, beanDesc.getClassInfo(), type);
if (newType != type) {
type = newType;
beanDesc = config.introspect(newType);
}
// We may also have a Builder type to consider...
Class<?> builder = beanDesc.findPOJOBuilder();
if (builder != null) {
return (JsonDeserializer<Object>) factory.createBuilderBasedDeserializer(
ctxt, type, beanDesc, builder);
}
// Or perhaps a Converter?
Converter<Object,Object> conv = beanDesc.findDeserializationConverter();
if (conv == null) { // nope, just construct in normal way
return (JsonDeserializer<Object>) _createDeserializer2(ctxt, factory, type, beanDesc);
}
// otherwise need to do bit of introspection
JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
// One more twist, as per [Issue#288]; probably need to get new BeanDesc
if (!delegateType.hasRawClass(type.getRawClass())) {
beanDesc = config.introspect(delegateType);
}
return new StdDelegatingDeserializer<Object>(conv, delegateType,
_createDeserializer2(ctxt, factory, delegateType, beanDesc));
}
protected JsonDeserializer<?> _createDeserializer2(DeserializationContext ctxt,
DeserializerFactory factory, JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
// If not, let's see which factory method to use:
if (type.isEnumType()) {
return factory.createEnumDeserializer(ctxt, type, beanDesc);
}
if (type.isContainerType
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>()) {
if (type.isArrayType()) {
return factory.createArrayDeserializer(ctxt, (ArrayType) type, beanDesc);
}
if (type.isMapLikeType()) {
MapLikeType mlt = (MapLikeType) type;
if (mlt.isTrueMapType()) {
return factory.createMapDeserializer(ctxt,(MapType) mlt, beanDesc);
}
return factory.createMapLikeDeserializer(ctxt, mlt, beanDesc);
}
if (type.isCollectionLikeType()) {
/* 03-Aug-2012, tatu: As per [Issue#40], one exception is if shape
* is to be Shape.OBJECT. Ideally we'd determine it bit later on
* (to allow custom handler checks), but that won't work for other
* reasons. So do it here.
*/
JsonFormat.Value format = beanDesc.findExpectedFormat(null);
if (format == null || format.getShape() != JsonFormat.Shape.OBJECT) {
CollectionLikeType clt = (CollectionLikeType) type;
if (clt.isTrueCollectionType()) {
return factory.createCollectionDeserializer(ctxt, (CollectionType) clt, beanDesc);
}
return factory.createCollectionLikeDeserializer(ctxt, clt, beanDesc);
}
}
}
if (JsonNode.class.isAssignableFrom(type.getRawClass())) {
return factory.createTreeDeserializer(config, type, beanDesc);
}
return factory.createBeanDeserializer(ctxt, type, beanDesc);
}
/**
* Helper method called to check if a class or method
* has annotation that tells which class to use for deserialization.
* Returns null if no such annotation found.
*/
protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationContext ctxt,
Annotated ann)
throws JsonMappingException
{
Object deserDef = ctxt.getAnnotationIntrospector().findDeserializer(ann);
if (deserDef == null) {
return null;
}
JsonDeserializer<Object> deser = ctxt.deserializerInstance(ann, deserDef);
// One more thing however: may need to also apply a converter:
return findConvertingDeserializer(ctxt, ann, deser);
}
/**
* Helper method that will
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> check whether given annotated entity (usually class,
* but may also be a property accessor) indicates that a {@link Converter} is to
* be used; and if so, to construct and return suitable serializer for it.
* If not, will simply return given serializer as is.
*/
protected JsonDeserializer<Object> findConvertingDeserializer(DeserializationContext ctxt,
Annotated a, JsonDeserializer<Object> deser)
throws JsonMappingException
{
Converter<Object,Object> conv = findConverter(ctxt, a);
if (conv == null) {
return deser;
}
JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
return (JsonDeserializer<Object>) new StdDelegatingDeserializer<Object>(conv, delegateType, deser);
}
protected Converter<Object,Object> findConverter(DeserializationContext ctxt,
Annotated a)
throws JsonMappingException
{
Object convDef = ctxt.getAnnotationIntrospector().findDeserializationConverter(a);
if (convDef == null) {
return null;
}
return ctxt.converterInstance(a, convDef);
}
/**
* Method called to see if given method has annotations that indicate
* a more specific type than what the argument specifies.
* If annotations are present, they must specify compatible Class;
* instance of which can be assigned using the method. This means
* that the Class has to be raw class of type, or its sub-class
* (or, implementing class if original Class instance is an interface).
*
* @param a Method or field that the type is associated with
* @param type Type derived from the setter argument
*
* @return Original type if no annotations are present; or a more
* specific type derived from it if type annotation(s) was found
*
* @throws JsonMappingException if invalid annotation is found
*/
private JavaType modifyTypeByAnnotation(DeserializationContext ctxt,
Annotated a, JavaType type)
throws JsonMappingException
{
// first: let's check class for the instance itself:
AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
Class<?> subclass = intr.findDeserializationType(a, type);
if (subclass != null) {
try {
type = type.narrowBy(subclass);
} catch (IllegalArgumentException iae) {
throw new JsonMapping
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Exception("Failed to narrow type "+type+" with concrete-type annotation (value "+subclass.getName()+"), method '"+a.getName()+"': "+iae.getMessage(), null, iae);
}
}
// then key class
if (type.isContainerType()) {
Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType());
if (keyClass != null) {
// illegal to use on non-Maps
if (!(type instanceof MapLikeType)) {
throw new JsonMappingException("Illegal key-type annotation: type "+type+" is not a Map(-like) type");
}
try {
type = ((MapLikeType) type).narrowKey(keyClass);
} catch (IllegalArgumentException iae) {
throw new JsonMappingException("Failed to narrow key type "+type+" with key-type annotation ("+keyClass.getName()+"): "+iae.getMessage(), null, iae);
}
}
JavaType keyType = type.getKeyType();
/* 21-Mar-2011, tatu: ... and associated deserializer too (unless already assigned)
* (not 100% why or how, but this does seem to get called more than once, which
* is not good: for now, let's just avoid errors)
*/
if (keyType != null && keyType.getValueHandler() == null) {
Object kdDef = intr.findKeyDeserializer(a);
if (kdDef != null) {
KeyDeserializer kd = ctxt.keyDeserializerInstance(a, kdDef);
if (kd != null) {
type = ((MapLikeType) type).withKeyValueHandler(kd);
keyType = type.getKeyType(); // just in case it's used below
}
}
}
// and finally content class; only applicable to structured types
Class<?> cc = intr.findDeserializationContentType(a, type.getContentType());
if (cc != null) {
try {
type = type.narrowContentsBy(cc);
} catch (IllegalArgumentException iae) {
throw new JsonMappingException("Failed to narrow content type "+type+" with content-type annotation ("+cc.getName()+"): "+iae.getMessage(), null, iae);
}
}
// ... as well as deserializer for contents:
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> JavaType contentType = type.getContentType();
if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception)
Object cdDef = intr.findContentDeserializer(a);
if (cdDef != null) {
JsonDeserializer<?> cd = null;
if (cdDef instanceof JsonDeserializer<?>) {
cdDef = (JsonDeserializer<?>) cdDef;
} else {
Class<?> cdClass = _verifyAsClass(cdDef, "findContentDeserializer", JsonDeserializer.None.class);
if (cdClass != null) {
cd = ctxt.deserializerInstance(a, cdClass);
}
}
if (cd != null) {
type = type.withContentValueHandler(cd);
}
}
}
}
return type;
}
private Class<?> _verifyAsClass(Object src, String methodName, Class<?> noneClass)
{
if (src == null) {
return null;
}
if (!(src instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector."+methodName+"() returned value of type "+src.getClass().getName()+": expected type JsonSerializer or Class<JsonSerializer> instead");
}
Class<?> cls = (Class<?>) src;
if (cls == noneClass || ClassUtil.isBogusClass(cls)) {
return null;
}
return cls;
}
/*
/**********************************************************
/* Overridable error reporting methods
/**********************************************************
*/
protected JsonDeserializer<Object> _handleUnknownValueDeserializer(JavaType type)
throws JsonMappingException
{
/* Let's try to figure out the reason, to give better error
* messages
*/
Class<?> rawClass = type.getRawClass();
if (!ClassUtil.isConcrete(rawClass)) {
throw new JsonMappingException("Can not find a Value deserializer for abstract type "+type);
}
throw new JsonMappingException("Can not find a Value deserializer for type "+type);
}
protected KeyDeserializer _handleUnknownKeyDeserializer(JavaType type)
throws JsonMappingException
{
throw new JsonMappingException("Can not find a (Map) Key deserializer for type "+type);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Serializer = null;
}
@SuppressWarnings("unchecked")
public StdDelegatingSerializer(Converter<Object,?> converter,
JavaType delegateType, JsonSerializer<?> delegateSerializer)
{
super(delegateType);
_converter = converter;
_delegateType = delegateType;
_delegateSerializer = (JsonSerializer<Object>) delegateSerializer;
}
/**
* Method used for creating resolved contextual instances. Must be
* overridden when sub-classing.
*/
protected StdDelegatingSerializer withDelegate(Converter<Object,?> converter,
JavaType delegateType, JsonSerializer<?> delegateSerializer)
{
if (getClass() != StdDelegatingSerializer.class) {
throw new IllegalStateException("Sub-class "+getClass().getName()+" must override 'withDelegate'");
}
return new StdDelegatingSerializer(converter, delegateType, delegateSerializer);
}
/*
/**********************************************************
/* Contextualization
/**********************************************************
*/
@Override
public void resolve(SerializerProvider provider) throws JsonMappingException
{
if ((_delegateSerializer != null)
&& (_delegateSerializer instanceof ResolvableSerializer)) {
((ResolvableSerializer) _delegateSerializer).resolve(provider);
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property)
throws JsonMappingException
{
// First: if already got serializer to delegate to, contextualize it:
if (_delegateSerializer != null) {
if (_delegateSerializer instanceof ContextualSerializer) {
JsonSerializer<?> ser = provider.handleSecondaryContextualization(_delegateSerializer, property);
if (ser == _delegateSerializer) {
return this;
}
return withDelegate(_converter, _delegateType, ser);
}
return this;
}
// Otherwise, need to locate serializer to delegate to. For that we need type information...
JavaType delegateType = _delegateType;
if (delegateType == null) {
delegateType = _converter.getOutputType(provider.getTypeFactory());
}
// and then find the thing...
return withDelegate(_converter, delegateType,
provider.findValueSerializer(delegateType, property));
}
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
protected Converter<Object, ?> getConverter() {
return _converter;
}
@Override
public JsonSerializer<?> getDelegatee() {
return _delegateSerializer;
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> }
/*
/**********************************************************
/* Serialization
/**********************************************************
*/
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException
{
Object delegateValue = convertValue(value);
// should we accept nulls?
if (delegateValue == null) {
provider.defaultSerializeNull(jgen);
return;
}
_delegateSerializer.serialize(delegateValue, jgen, provider);
}
@Override
public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonProcessingException
{
/* 03-Oct-2012, tatu: This is actually unlikely to work ok... but for now,
* let's give it a chance?
*/
Object delegateValue = convertValue(value);
_delegateSerializer.serializeWithType(delegateValue, jgen, provider, typeSer);
}
@Override
public boolean isEmpty(Object value)
{
Object delegateValue = convertValue(value);
return _delegateSerializer.isEmpty(delegateValue);
}
/*
/**********************************************************
/* Schema functionality
/**********************************************************
*/
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
if (_delegateSerializer instanceof SchemaAware) {
return ((SchemaAware) _delegateSerializer).getSchema(provider, typeHint);
}
return super.getSchema(provider, typeHint);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint,
boolean isOptional) throws JsonMappingException
{
if (_delegateSerializer instanceof SchemaAware) {
return ((SchemaAware) _delegateSerializer).getSchema(provider, typeHint, isOptional);
}
return super.getSchema(provider, typeHint);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
/* 03-Sep-2012, tatu: Not sure if this can be made to really work
* properly... but for now, try this:
*/
_delegateSerializer.acceptJsonFormatVisitor(visitor, typeHint);
}
/*
/**********************************************************
/* Overridable methods
/**********************************************************
*/
/**
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>field.getDeclaringClass(); }
@Override
public Member getMember() { return _field; }
@Override
public void setValue(Object pojo, Object value) throws IllegalArgumentException
{
try {
_field.set(pojo, value);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Failed to setValue() for field "
+getFullName()+": "+e.getMessage(), e);
}
}
@Override
public Object getValue(Object pojo) throws IllegalArgumentException
{
try {
return _field.get(pojo);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Failed to getValue() for field "
+getFullName()+": "+e.getMessage(), e);
}
}
/*
/**********************************************************
/* Extended API, generic
/**********************************************************
*/
public String getFullName() {
return getDeclaringClass().getName() + "#" + getName();
}
public int getAnnotationCount() { return _annotations.size(); }
@Override
public String toString()
{
return "[field "+getFullName()+"]";
}
/*
/**********************************************************
/* JDK serialization handling
/**********************************************************
*/
Object writeReplace() {
return new AnnotatedField(new Serialization(_field));
}
Object readResolve() {
Class<?> clazz = _serialization.clazz;
try {
Field f = clazz.getDeclaredField(_serialization.name);
// 06-Oct-2012, tatu: Has "lost" its security override, may need to force back
if (!f.isAccessible()) {
ClassUtil.checkAndFixAccess(f);
}
return new AnnotatedField(f, null);
} catch (Exception e) {
throw new IllegalArgumentException("Could not find method '"+_serialization.name
+"' from Class '"+clazz.getName());
}
}
/**
* Helper class that is used as the workaround to persist
* Field references. It basically just stores declaring class
* and field name.
*/
private final static class Serialization
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected Class<?> clazz;
protected String name;
public Serialization(Field f) {
clazz = f.getDeclaringClass();
name = f.getName();
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>)
throws JsonMappingException
{
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
* checking here since we finally know for sure the property,
* and it may have overrides
*/
JsonSerializer<?> ser = null;
JsonSerializer<?> keySer = null;
final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember();
// First: if we have a property, may have property-annotation overrides
if (propertyAcc != null && intr != null) {
Object serDef = intr.findKeySerializer(propertyAcc);
if (serDef != null) {
keySer = provider.serializerInstance(propertyAcc, serDef);
}
serDef = intr.findContentSerializer(propertyAcc);
if (serDef != null) {
ser = provider.serializerInstance(propertyAcc, serDef);
}
}
if (ser == null) {
ser = _valueSerializer;
}
// [Issue#124]: May have a content converter
ser = findConvertingContentSerializer(provider, property, ser);
if (ser == null) {
// 30-Sep-2012, tatu: One more thing -- if explicit content type is annotated,
// we can consider it a static case as well.
// 20-Aug-2013, tatu: Need to avoid trying to access serializer for java.lang.Object tho
if ((_valueTypeIsStatic && _valueType.getRawClass() != Object.class)
|| hasContentTypeAnnotation(provider, property)) {
ser = provider.findValueSerializer(_valueType, property);
}
} else {
ser = provider.handleSecondaryContextualization(ser, property);
}
if (keySer == null) {
keySer = _keySerializer;
}
if (keySer == null) {
keySer = provider.findKeySerializer(_keyType, property);
} else {
keySer = provider.handleSecondaryContextualization(keySer, property);
}
HashSet<String> ignored = _ignoredEntries;
boolean sortKeys = false;
if (intr != null && propertyAcc != null) {
String[] more
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, provider);
} else {
// [JACKSON-314] skip entries with null values?
if (skipNulls && valueElem == null) continue;
// One twist: is entry ignorable? If so, skip
if (ignored != null && ignored.contains(keyElem)) continue;
keySerializer.serialize(keyElem, jgen, provider);
}
// And then value
if (valueElem == null) {
provider.defaultSerializeNull(jgen);
} else {
Class<?> cc = valueElem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
if (_valueType.hasGenericTypes()) {
serializer = _findAndAddDynamic(serializers,
provider.constructSpecializedType(_valueType, cc), provider);
} else {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
serializers = _dynamicValueSerializers;
}
try {
serializer.serialize(valueElem, jgen, provider);
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
String keyDesc = ""+keyElem;
wrapAndThrow(provider, e, value, keyDesc);
}
}
}
}
/**
* Method called to serialize fields, when the value type is statically known,
* so that value serializer is passed and does not need to be fetched from
* provider.
*/
protected void serializeFieldsUsing(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
JsonSerializer<Object> ser)
throws IOException, JsonGenerationException
{
final JsonSerializer<Object> keySerializer = _keySerializer;
final HashSet<String> ignored = _ignoredEntries;
final TypeSerializer typeSer = _valueTypeSerializer;
final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
for (Map.Entry<?,?> entry : value.entrySet()) {
Object valueElem = entry.getValue();
Object keyElem = entry.getKey();
if (keyElem == null) {
provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
} else {
// [JACKSON-314] also may need to skip entries with null values
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
if (skipNulls && valueElem == null) continue;
if (ignored != null && ignored.contains(keyElem)) continue;
keySerializer.serialize(keyElem, jgen, provider);
}
if (valueElem == null) {
provider.defaultSerializeNull(jgen);
} else {
try {
if (typeSer == null) {
ser.serialize(valueElem, jgen, provider);
} else {
ser.serializeWithType(valueElem, jgen, provider, typeSer);
}
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
String keyDesc = ""+keyElem;
wrapAndThrow(provider, e, value, keyDesc);
}
}
}
}
/**
* Helper method used when we have a JSON Filter to use for potentially
* filtering out Map entries.
*<p>
* NOTE: initially only called externally, by <code>AnyGetterWriter</code>
*
* @since 2.3
*/
public void serializeFilteredFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
PropertyFilter filter)
throws IOException, JsonGenerationException
{
final HashSet<String> ignored = _ignoredEntries;
final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
PropertySerializerMap serializers = _dynamicValueSerializers;
final MapProperty prop = new MapProperty(_valueTypeSerializer);
for (Map.Entry<?,?> entry : value.entrySet()) {
// First, serialize key
final Object keyElem = entry.getKey();
final Object valueElem = entry.getValue();
JsonSerializer<Object> keySer;
if (keyElem == null) {
keySer = provider.findNullKeySerializer(_keyType, _property);
} else {
// [JACKSON-314] skip entries with null values?
if (skipNulls && valueElem == null) continue;
// One twist: is entry ignorable? If so, skip
if (ignored != null && ignored.contains(keyElem)) continue;
keySer = _keySerializer;
}
JsonSerializer<Object> valueSer;
// And then value
if (valueElem == null) {
valueSer = provider.getDefaultNullValue
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Serializer();
} else {
Class<?> cc = valueElem.getClass();
valueSer = serializers.serializerFor(cc);
if (valueSer == null) {
if (_valueType.hasGenericTypes()) {
valueSer = _findAndAddDynamic(serializers,
provider.constructSpecializedType(_valueType, cc), provider);
} else {
valueSer = _findAndAddDynamic(serializers, cc, provider);
}
serializers = _dynamicValueSerializers;
}
}
prop.reset(keyElem, valueElem, keySer, valueSer);
try {
filter.serializeAsField(value, jgen, provider, prop);
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
String keyDesc = ""+keyElem;
wrapAndThrow(provider, e, value, keyDesc);
}
}
}
protected void serializeTypedFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
final JsonSerializer<Object> keySerializer = _keySerializer;
JsonSerializer<Object> prevValueSerializer = null;
Class<?> prevValueClass = null;
final HashSet<String> ignored = _ignoredEntries;
final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
for (Map.Entry<?,?> entry : value.entrySet()) {
Object valueElem = entry.getValue();
// First, serialize key
Object keyElem = entry.getKey();
if (keyElem == null) {
provider.findNullKeySerializer(_keyType, _property).serialize(null, jgen, provider);
} else {
// [JACKSON-314] also may need to skip entries with null values
if (skipNulls && valueElem == null) continue;
// One twist: is entry ignorable? If so, skip
if (ignored != null && ignored.contains(keyElem)) continue;
keySerializer.serialize(keyElem, jgen, provider);
}
// And then value
if (valueElem == null) {
provider.defaultSerializeNull(jgen);
} else {
Class<?> cc = valueElem.getClass();
JsonSerializer<Object> currSerializer;
if (cc == prevValueClass) {
currSerializer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> = prevValueSerializer;
} else {
if (_valueType.hasGenericTypes()) {
currSerializer = provider.findValueSerializer(provider.constructSpecializedType(_valueType, cc), _property);
} else {
currSerializer = provider.findValueSerializer(cc, _property);
}
prevValueSerializer = currSerializer;
prevValueClass = cc;
}
try {
currSerializer.serializeWithType(valueElem, jgen, provider, _valueTypeSerializer);
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
String keyDesc = ""+keyElem;
wrapAndThrow(provider, e, value, keyDesc);
}
}
}
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
ObjectNode o = createSchemaNode("object", true);
//(ryan) even though it's possible to statically determine the "value" type of the map,
// there's no way to statically determine the keys, so the "Entries" can't be determined.
return o;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonMapFormatVisitor v2 = (visitor == null) ? null : visitor.expectMapFormat(typeHint);
if (v2 != null) {
v2.keyFormat(_keySerializer, _keyType);
JsonSerializer<?> valueSer = _valueSerializer;
if (valueSer == null) {
valueSer = _findAndAddDynamic(_dynamicValueSerializers,
_valueType, visitor.getProvider());
}
v2.valueFormat(valueSer, _valueType);
}
}
/*
/**********************************************************
/* Internal helper methods
/**********************************************************
*/
protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
// did we get a new map of serializers? If so, start using it
if (map != result.map) {
_dynamicValueSerializers = result.map;
}
return result.serializer;
}
protected final
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
JavaType type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
if (map != result.map) {
_dynamicValueSerializers = result.map;
}
return result.serializer;
}
protected Map<?,?> _orderEntries(Map<?,?> input)
{
// minor optimization: may already be sorted?
if (input instanceof SortedMap<?,?>) {
return input;
}
return new TreeMap<Object,Object>(input);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat;
@JacksonStdImpl
public class SqlTimeSerializer
extends StdScalarSerializer<java.sql.Time>
{
public SqlTimeSerializer() { super(java.sql.Time.class); }
@Override
public void serialize(java.sql.Time value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
jgen.writeString(value.toString());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonStringFormatVisitor v2 = (visitor == null) ? null : visitor.expectStringFormat(typeHint);
if (v2 != null) {
v2.format(JsonValueFormat.DATE_TIME);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> single value array for single 'String' value but there was more than a single value in the array");
}
return parsed;
}
String value = jp.getValueAsString();
if (value != null) {
return value;
}
throw ctxt.mappingException(String.class, jp.getCurrentToken());
}
/**
* Helper method called to determine if we are seeing String value of
* "null", and, further, that it should be coerced to null just like
* null token.
*
* @since 2.3
*/
protected boolean _hasTextualNull(String value) {
return "null".equals(value);
}
protected final boolean _isNegInf(String text) {
return "-Infinity".equals(text) || "-INF".equals(text);
}
protected final boolean _isPosInf(String text) {
return "Infinity".equals(text) || "INF".equals(text);
}
protected final boolean _isNaN(String text) { return "NaN".equals(text); }
/*
/****************************************************
/* Helper methods for sub-classes, resolving dependencies
/****************************************************
*/
/**
* Helper method used to locate deserializers for properties the
* type this deserializer handles contains (usually for properties of
* bean types)
*
* @param type Type of property to deserialize
* @param property Actual property object (field, method, constuctor parameter) used
* for passing deserialized values; provided so deserializer can be contextualized if necessary (since 1.7)
*/
protected JsonDeserializer<Object> findDeserializer(DeserializationContext ctxt,
JavaType type, BeanProperty property)
throws JsonMappingException
{
return ctxt.findContextualValueDeserializer(type, property);
}
/*
/**********************************************************
/* Helper methods for sub-classes, deserializer construction
/**********************************************************
*/
/**
* Helper method that can be used to see if specified property has annotation
* indicating that a converter is to be used for contained values (contents
* of structured types; array/List/Map values)
*
* @param existingDeserializer (optional) configured content
* serializer if one already exists.
*
* @since 2.2
*/
protected JsonDeserializer<?> findConvertingContentDeserializer(DeserializationContext ctxt,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
BeanProperty prop, JsonDeserializer<?> existingDeserializer)
throws JsonMappingException
{
final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
if (intr != null && prop != null) {
Object convDef = intr.findDeserializationContentConverter(prop.getMember());
if (convDef != null) {
Converter<Object,Object> conv = ctxt.converterInstance(prop.getMember(), convDef);
JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
if (existingDeserializer == null) {
existingDeserializer = ctxt.findContextualValueDeserializer(delegateType, prop);
}
return new StdDelegatingDeserializer<Object>(conv, delegateType, existingDeserializer);
}
}
return existingDeserializer;
}
/*
/**********************************************************
/* Helper methods for sub-classes, problem reporting
/**********************************************************
*/
/**
* Method called to deal with a property that did not map to a known
* Bean property. Method can deal with the problem as it sees fit (ignore,
* throw exception); but if it does return, it has to skip the matching
* Json content parser has.
*<p>
* NOTE: method signature was changed in version 1.5; explicit JsonParser
* <b>must</b> be passed since it may be something other than what
* context has. Prior versions did not include the first parameter.
*
* @param jp Parser that points to value of the unknown property
* @param ctxt Context for deserialization; allows access to the parser,
* error reporting functionality
* @param instanceOrClass Instance that is being populated by this
* deserializer, or if not known, Class that would be instantiated.
* If null, will assume type is what {@link #getValueClass} returns.
* @param propName Name of the property that can not be mapped
*/
protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object instanceOrClass, String propName)
throws IOException
{
if (instanceOrClass == null) {
instanceOrClass = handledType();
}
// Maybe we have configured handler(s) to take care of it?
if (ctxt.handleUnknownProperty(jp, this, instanceOrClass, propName)) {
return;
}
// Nope, not handled
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Instantiator = valueInstantiator;
_delegateDeserializer = (JsonDeserializer<Object>) delegateDeser;
}
protected StringCollectionDeserializer withResolved(JsonDeserializer<?> delegateDeser,
JsonDeserializer<?> valueDeser)
{
if ((_valueDeserializer == valueDeser) && (_delegateDeserializer == delegateDeser)) {
return this;
}
return new StringCollectionDeserializer(_collectionType,
_valueInstantiator, delegateDeser, valueDeser);
}
/*
/**********************************************************
/* Validation, post-processing
/**********************************************************
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
// May need to resolve types for delegate-based creators:
JsonDeserializer<Object> delegate = null;
if (_valueInstantiator != null) {
AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator();
if (delegateCreator != null) {
JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
delegate = findDeserializer(ctxt, delegateType, property);
}
}
JsonDeserializer<?> valueDeser = _valueDeserializer;
if (valueDeser == null) {
// #125: May have a content converter
valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser);
if (valueDeser == null) {
// And we may also need to get deserializer for String
valueDeser = ctxt.findContextualValueDeserializer( _collectionType.getContentType(), property);
}
} else { // if directly assigned, probably not yet contextual, so:
valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property);
}
if (isDefaultDeserializer(valueDeser)) {
valueDeser = null;
}
return withResolved(delegate, valueDeser);
}
/*
/**********************************************************
/* ContainerDeserializerBase API
/**********************************************************
*/
@Override
public JavaType getContentType() {
return _collectionType.getContentType();
}
@SuppressWarnings("unchecked")
@Override
public JsonDeserializer<Object> getContentDeserializer() {
JsonDeserializer<?> deser = _valueDeserializer;
return (JsonDeserializer<Object>) deser;
}
/*
/**********************************************************
/* JsonDeserializer API
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> /**********************************************************
*/
@SuppressWarnings("unchecked")
@Override
public Collection<String> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
if (_delegateDeserializer != null) {
return (Collection<String>) _valueInstantiator.createUsingDelegate(ctxt,
_delegateDeserializer.deserialize(jp, ctxt));
}
final Collection<String> result = (Collection<String>) _valueInstantiator.createUsingDefault(ctxt);
return deserialize(jp, ctxt, result);
}
@Override
public Collection<String> deserialize(JsonParser jp, DeserializationContext ctxt,
Collection<String> result)
throws IOException
{
// Ok: must point to START_ARRAY
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt, result);
}
if (_valueDeserializer != null) {
return deserializeUsingCustom(jp, ctxt, result, _valueDeserializer);
}
JsonToken t;
try {
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null;
} else {
value = _parseString(jp, ctxt);
}
result.add(value);
}
} catch (Exception e) {
// note: pass String.class, not String[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, String.class, result.size());
}
return result;
}
private Collection<String> deserializeUsingCustom(JsonParser jp, DeserializationContext ctxt,
Collection<String> result, final JsonDeserializer<String> deser) throws IOException
{
JsonToken t;
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
String value;
if (t == JsonToken.VALUE_NULL) {
value = deser.getNullValue();
} else {
value = deser.deserialize(jp, ctxt);
}
result.add(value);
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
// In future
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.exc;
import java.util.*;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Specialized {@link JsonMappingException} sub-class used to indicate
* case where an explicitly ignored property is encountered, and mapper
* is configured to consider this an error.
*
* @since 2.3
*/
public class IgnoredPropertyException
extends PropertyBindingException
{
private static final long serialVersionUID = 1L;
public IgnoredPropertyException(String msg, JsonLocation loc,
Class<?> referringClass, String propName,
Collection<Object> propertyIds)
{
super(msg, loc, referringClass, propName, propertyIds);
}
/**
* Factory method used for constructing instances of this exception type.
*
* @param jp Underlying parser used for reading input being used for data-binding
* @param fromObjectOrClass Reference to either instance of problematic type (
* if available), or if not, type itself
* @param propertyName Name of unrecognized property
* @param propertyIds (optional, null if not available) Set of properties that
* type would recognize, if completely known: null if set can not be determined.
*/
public static IgnoredPropertyException from(JsonParser jp,
Object fromObjectOrClass, String propertyName,
Collection<Object> propertyIds)
{
if (fromObjectOrClass == null) {
throw new IllegalArgumentException();
}
Class<?> ref;
if (fromObjectOrClass instanceof Class<?>) {
ref = (Class<?>) fromObjectOrClass;
} else {
ref = fromObjectOrClass.getClass();
}
String msg = "Ignored field \""+propertyName+"\" (class "+ref.getName()
+") encountered; mapper configured not to allow this";
IgnoredPropertyException e = new IgnoredPropertyException(msg,
jp.getCurrentLocation(), ref, propertyName, propertyIds);
// but let's also ensure path includes this last (missing) segment
e.prependPath(fromObjectOrClass, propertyName);
return e;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.lang.reflect.Type;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* This is a simple dummy serializer that will just output literal
* JSON null value whenever serialization is requested.
* Used as the default "null serializer" (which is used for serializing
* null object references unless overridden), as well as for some
* more exotic types (java.lang.Void).
*/
@JacksonStdImpl
public class NullSerializer
extends StdSerializer<Object>
{
public final static NullSerializer instance = new NullSerializer();
private NullSerializer() { super(Object.class); }
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
jgen.writeNull();
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return createSchemaNode("null");
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectNullFormat(typeHint);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>length;
BeanPropertyWriter[] result = new BeanPropertyWriter[len];
for (int i = 0; i < len; ++i) {
BeanPropertyWriter bpw = props[i];
if (bpw != null) {
result[i] = bpw.rename(transformer);
}
}
return result;
}
/*
/**********************************************************
/* Post-constriction processing: resolvable, contextual
/**********************************************************
*/
/**
* We need to implement {@link ResolvableSerializer} to be able to
* properly handle cyclic type references.
*/
@Override
public void resolve(SerializerProvider provider)
throws JsonMappingException
{
int filteredCount = (_filteredProps == null) ? 0 : _filteredProps.length;
for (int i = 0, len = _props.length; i < len; ++i) {
BeanPropertyWriter prop = _props[i];
// let's start with null serializer resolution actually
if (!prop.willSuppressNulls() && !prop.hasNullSerializer()) {
JsonSerializer<Object> nullSer = provider.findNullValueSerializer(prop);
if (nullSer != null) {
prop.assignNullSerializer(nullSer);
// also: remember to replace filtered property too? (see [JACKSON-364])
if (i < filteredCount) {
BeanPropertyWriter w2 = _filteredProps[i];
if (w2 != null) {
w2.assignNullSerializer(nullSer);
}
}
}
}
if (prop.hasSerializer()) {
continue;
}
// [Issue#124]: allow use of converters
JsonSerializer<Object> ser = findConvertingSerializer(provider, prop);
if (ser == null) {
// Was the serialization type hard-coded? If so, use it
JavaType type = prop.getSerializationType();
// It not, we can use declared return type if and only if declared type is final:
// if not, we don't really know the actual type until we get the instance.
if (type == null) {
type = provider.constructType(prop.getGenericPropertyType());
if (!type.isFinal()) {
if (type.isContainerType() || type.containedTypeCount() > 0)
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> {
prop.setNonTrivialBaseType(type);
}
continue;
}
}
ser = provider.findValueSerializer(type, prop);
/* 04-Feb-2010, tatu: We may have stashed type serializer for content types
* too, earlier; if so, it's time to connect the dots here:
*/
if (type.isContainerType()) {
TypeSerializer typeSer = type.getContentType().getTypeHandler();
if (typeSer != null) {
// for now, can do this only for standard containers...
if (ser instanceof ContainerSerializer<?>) {
// ugly casts... but necessary
@SuppressWarnings("unchecked")
JsonSerializer<Object> ser2 = (JsonSerializer<Object>)((ContainerSerializer<?>) ser).withValueTypeSerializer(typeSer);
ser = ser2;
}
}
}
}
prop.assignSerializer(ser);
// and maybe replace filtered property too? (see [JACKSON-364])
if (i < filteredCount) {
BeanPropertyWriter w2 = _filteredProps[i];
if (w2 != null) {
w2.assignSerializer(ser);
}
}
}
// also, any-getter may need to be resolved
if (_anyGetterWriter != null) {
_anyGetterWriter.resolve(provider);
}
}
/**
* Helper method that can be used to see if specified property is annotated
* to indicate use of a converter for property value (in case of container types,
* it is container type itself, not key or content type).
*
* @since 2.2
*/
protected JsonSerializer<Object> findConvertingSerializer(SerializerProvider provider,
BeanPropertyWriter prop)
throws JsonMappingException
{
final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
if (intr != null) {
Object convDef = intr.findSerializationConverter(prop.getMember());
if (convDef != null) {
Converter<Object,Object> conv = provider.converterInstance(prop.getMember(), convDef);
JavaType delegateType = conv.getOutputType(provider.getTypeFactory());
JsonSerializer<?> ser = provider.findValueSerializer(delegateType, prop);
return new StdDelegatingSerializer(conv, delegateType, ser);
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> }
}
return null;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
ObjectIdWriter oiw = _objectIdWriter;
String[] ignorals = null;
Object newFilterId = null;
final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
final AnnotatedMember accessor = (property == null || intr == null)
? null : property.getMember();
// First: may have an override for Object Id:
if (accessor != null) {
ignorals = intr.findPropertiesToIgnore(accessor);
ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
if (objectIdInfo == null) {
// no ObjectId override, but maybe ObjectIdRef?
if (oiw != null) {
objectIdInfo = intr.findObjectReferenceInfo(accessor,
new ObjectIdInfo(NAME_FOR_OBJECT_REF, null, null, null));
oiw = _objectIdWriter.withAlwaysAsId(objectIdInfo.getAlwaysAsId());
}
} else {
/* Ugh: mostly copied from BeanSerializerBase: but can't easily
* change it to be able to move to SerializerProvider (where it
* really belongs)
*/
// 2.1: allow modifications by "id ref" annotations as well:
objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo);
ObjectIdGenerator<?> gen;
Class<?> implClass = objectIdInfo.getGeneratorType();
JavaType type = provider.constructType(implClass);
JavaType idType = provider.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
// Property-based generator is trickier
if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work
String propName = objectIdInfo.getPropertyName().getSimpleName();
BeanPropertyWriter idProp = null;
for (int i = 0, len = _props.length ;; ++i) {
if (i == len) {
throw new IllegalArgumentException("Invalid Object Id definition for "+_handledType.getName()
+": can not find property with name '"+propName+"'");
}
BeanPropertyWriter prop = _props[i];
if (propName.equals(prop
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> (typeStr == null) {
typeSer.writeTypeSuffixForObject(bean, jgen);
} else {
typeSer.writeCustomTypeSuffixForObject(bean, jgen, typeStr);
}
}
private final String _customTypeId(Object bean)
{
final Object typeId = _typeId.getValue(bean);
if (typeId == null) {
return "";
}
return (typeId instanceof String) ? (String) typeId : typeId.toString();
}
/*
/**********************************************************
/* Field serialization methods
/**********************************************************
*/
protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
final BeanPropertyWriter[] props;
if (_filteredProps != null && provider.getActiveView() != null) {
props = _filteredProps;
} else {
props = _props;
}
int i = 0;
try {
for (final int len = props.length; i < len; ++i) {
BeanPropertyWriter prop = props[i];
if (prop != null) { // can have nulls in filtered list
prop.serializeAsField(bean, jgen, provider);
}
}
if (_anyGetterWriter != null) {
_anyGetterWriter.getAndSerialize(bean, jgen, provider);
}
} catch (Exception e) {
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
wrapAndThrow(provider, e, bean, name);
} catch (StackOverflowError e) {
/* 04-Sep-2009, tatu: Dealing with this is tricky, since we do not
* have many stack frames to spare... just one or two; can't
* make many calls.
*/
JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)", e);
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
mapE.prependPath(new JsonMappingException.Reference(bean, name));
throw mapE;
}
}
/**
* Alternative serialization method that gets called when there is a
* {@link PropertyFilter} that needs to be called to
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> determine
* which properties are to be serialized (and possibly how)
*/
protected void serializeFieldsFiltered(Object bean, JsonGenerator jgen,
SerializerProvider provider)
throws IOException, JsonGenerationException
{
/* note: almost verbatim copy of "serializeFields"; copied (instead of merged)
* so that old method need not add check for existence of filter.
*/
final BeanPropertyWriter[] props;
if (_filteredProps != null && provider.getActiveView() != null) {
props = _filteredProps;
} else {
props = _props;
}
final PropertyFilter filter = findPropertyFilter(provider, _propertyFilterId, bean);
// better also allow missing filter actually..
if (filter == null) {
serializeFields(bean, jgen, provider);
return;
}
int i = 0;
try {
for (final int len = props.length; i < len; ++i) {
BeanPropertyWriter prop = props[i];
if (prop != null) { // can have nulls in filtered list
filter.serializeAsField(bean, jgen, provider, prop);
}
}
if (_anyGetterWriter != null) {
_anyGetterWriter.getAndFilter(bean, jgen, provider, filter);
}
} catch (Exception e) {
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
wrapAndThrow(provider, e, bean, name);
} catch (StackOverflowError e) {
JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)", e);
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
mapE.prependPath(new JsonMappingException.Reference(bean, name));
throw mapE;
}
}
@Deprecated
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
ObjectNode o = createSchemaNode("object", true);
// [JACKSON-813]: Add optional JSON Schema id attribute, if found
// NOTE: not optimal, does NOT go through AnnotationIntrospector etc:
JsonSerializableSchema ann = _handledType.getAnnotation(JsonSerializableSchema.class);
if (ann != null
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>) {
String id = ann.id();
if (id != null && id.length() > 0) {
o.put("id", id);
}
}
//todo: should the classname go in the title?
//o.put("title", _className);
ObjectNode propertiesNode = o.objectNode();
final PropertyFilter filter;
if (_propertyFilterId != null) {
filter = findPropertyFilter(provider, _propertyFilterId, null);
} else {
filter = null;
}
for (int i = 0; i < _props.length; i++) {
BeanPropertyWriter prop = _props[i];
if (filter == null) {
prop.depositSchemaProperty(propertiesNode, provider);
} else {
filter.depositSchemaProperty(prop, propertiesNode, provider);
}
}
o.put("properties", propertiesNode);
return o;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
//deposit your output format
if (visitor == null) {
return;
}
JsonObjectFormatVisitor objectVisitor = visitor.expectObjectFormat(typeHint);
if (objectVisitor == null) {
return;
}
if (_propertyFilterId != null) {
PropertyFilter filter = findPropertyFilter(visitor.getProvider(),
_propertyFilterId, null);
for (int i = 0; i < _props.length; i++) {
filter.depositSchemaProperty(_props[i], objectVisitor, visitor.getProvider());
}
} else {
for (int i = 0; i < _props.length; i++) {
_props[i].depositSchemaProperty(objectVisitor);
}
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> = new LinkedHashMap<Object,Object>();
for (int i = 0, len = args.length; i < len; i += 2) {
map.put(args[i], args[i+1]);
}
return m.writeValueAsString(map);
}
/*
/**********************************************************
/* Helper methods, deserialization
/**********************************************************
*/
protected <T> T readAndMapFromString(String input, Class<T> cls)
throws IOException
{
return readAndMapFromString(SHARED_MAPPER, input, cls);
}
protected <T> T readAndMapFromString(ObjectMapper m, String input, Class<T> cls)
throws IOException
{
return (T) m.readValue("\""+input+"\"", cls);
}
/*
/**********************************************************
/* Helper methods, other
/**********************************************************
*/
protected TimeZone getUTCTimeZone() {
return TimeZone.getTimeZone("GMT");
}
protected byte[] utf8Bytes(String str) {
try {
return str.getBytes("UTF-8");
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
protected String aposToQuotes(String json) {
return json.replace("'", "\"");
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.impl;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* Special bogus "serializer" that will throw
* {@link JsonGenerationException} if its {@link #serialize}
* gets invoked. Most commonly registered as handler for unknown types,
* as well as for catching unintended usage (like trying to use null
* as Map/Object key).
*/
public final class FailingSerializer
extends StdSerializer<Object>
{
final String _msg;
public FailingSerializer(String msg) {
super(Object.class);
_msg = msg;
}
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
throw new JsonGenerationException(_msg);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return null;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
{
;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
@SuppressWarnings("serial")
public class TestCollectionDeserialization
extends BaseMapTest
{
enum Key {
KEY1, KEY2, WHATEVER;
}
@JsonDeserialize(using=ListDeserializer.class)
static class CustomList extends LinkedList<String> { }
static class ListDeserializer extends StdDeserializer<CustomList>
{
public ListDeserializer() { super(CustomList.class); }
@Override
public CustomList deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
CustomList result = new CustomList();
result.add(jp.getText());
return result;
}
}
static class XBean {
public int x;
}
// [Issue#199]
static class ListAsIterable {
public Iterable<String> values;
}
static class ListAsIterableX {
public Iterable<XBean> nums;
}
static class KeyListBean {
public List<Key> keys;
}
/*
/**********************************************************
/* Test methods
/**********************************************************
*/
private final static ObjectMapper MAPPER = new ObjectMapper();
public void testUntypedList() throws Exception
{
// to get "untyped" default List, pass Object.class
String JSON = "[ \"text!\", true, null, 23 ]";
// Not a guaranteed cast theoretically, but will work:
// (since we know that Jackson will construct an ArrayList here...)
Object value = MAPPER.readValue(JSON, Object.class);
assertNotNull(value);
assertTrue(value instanceof ArrayList<?>);
List<?> result = (List<?>) value;
assertEquals(4, result.size());
assertEquals("text!", result.get(0));
assertEquals(Boolean.TRUE, result.get(1));
assertNull(result.get(2));
assertEquals(Integer.valueOf(23), result
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.get(3));
}
public void testExactStringCollection() throws Exception
{
// to get typing, must use type reference
String JSON = "[ \"a\", \"b\" ]";
List<String> result = MAPPER.readValue(JSON, new TypeReference<ArrayList<String>>() { });
assertNotNull(result);
assertEquals(ArrayList.class, result.getClass());
assertEquals(2, result.size());
assertEquals("a", result.get(0));
assertEquals("b", result.get(1));
}
public void testHashSet() throws Exception
{
String JSON = "[ \"KEY1\", \"KEY2\" ]";
EnumSet<Key> result = MAPPER.readValue(JSON, new TypeReference<EnumSet<Key>>() { });
assertNotNull(result);
assertTrue(EnumSet.class.isAssignableFrom(result.getClass()));
assertEquals(2, result.size());
assertTrue(result.contains(Key.KEY1));
assertTrue(result.contains(Key.KEY2));
assertFalse(result.contains(Key.WHATEVER));
}
/// Test to verify that @JsonDeserialize.using works as expected
public void testCustomDeserializer() throws IOException
{
CustomList result = MAPPER.readValue(quote("abc"), CustomList.class);
assertEquals(1, result.size());
assertEquals("abc", result.get(0));
}
// Testing [JACKSON-526], "implicit JSON array" for single-element arrays,
// mostly produced by Jettison, Badgerfish conversions (from XML)
@SuppressWarnings("unchecked")
public void testImplicitArrays() throws Exception
{
// can't share mapper, custom configs (could create ObjectWriter tho)
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
// first with simple scalar types (numbers), with collections
List<Integer> ints = mapper.readValue("4", List.class);
assertEquals(1, ints.size());
assertEquals(Integer.valueOf(4), ints.get(0));
List<String> strings = mapper.readValue(quote("abc"), new TypeReference<ArrayList<String>>() { });
assertEquals(1, strings.size());
assertEquals("abc", strings.get(0));
// and arrays:
int[] intArray = mapper
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.readValue("-7", int[].class);
assertEquals(1, intArray.length);
assertEquals(-7, intArray[0]);
String[] stringArray = mapper.readValue(quote("xyz"), String[].class);
assertEquals(1, stringArray.length);
assertEquals("xyz", stringArray[0]);
// and then with Beans:
List<XBean> xbeanList = mapper.readValue("{\"x\":4}", new TypeReference<List<XBean>>() { });
assertEquals(1, xbeanList.size());
assertEquals(XBean.class, xbeanList.get(0).getClass());
Object ob = mapper.readValue("{\"x\":29}", XBean[].class);
XBean[] xbeanArray = (XBean[]) ob;
assertEquals(1, xbeanArray.length);
assertEquals(XBean.class, xbeanArray[0].getClass());
}
// [JACKSON-620]: allow "" to mean 'null' for Maps
public void testFromEmptyString() throws Exception
{
ObjectReader r = MAPPER.reader(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
List<?> result = r.withType(List.class).readValue(quote(""));
assertNull(result);
}
// [Issue#161]
public void testArrayBlockingQueue() throws Exception
{
// ok to skip polymorphic type to get Object
ArrayBlockingQueue<?> q = MAPPER.readValue("[1, 2, 3]", ArrayBlockingQueue.class);
assertNotNull(q);
assertEquals(3, q.size());
assertEquals(Integer.valueOf(1), q.take());
assertEquals(Integer.valueOf(2), q.take());
assertEquals(Integer.valueOf(3), q.take());
}
// [Issue#199]
public void testIterableWithStrings() throws Exception
{
String JSON = "{ \"values\":[\"a\",\"b\"]}";
ListAsIterable w = MAPPER.readValue(JSON, ListAsIterable.class);
assertNotNull(w);
assertNotNull(w.values);
Iterator<String> it = w.values.iterator();
assertTrue(it.hasNext());
assertEquals("a", it.next());
assertEquals("b", it.next());
assertFalse(it.hasNext());
}
public void testIterableWithBeans() throws Exception
{
String
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> JSON = "{ \"nums\":[{\"x\":1},{\"x\":2}]}";
ListAsIterableX w = MAPPER.readValue(JSON, ListAsIterableX.class);
assertNotNull(w);
assertNotNull(w.nums);
Iterator<XBean> it = w.nums.iterator();
assertTrue(it.hasNext());
XBean xb = it.next();
assertNotNull(xb);
assertEquals(1, xb.x);
xb = it.next();
assertEquals(2, xb.x);
assertFalse(it.hasNext());
}
// for [Issue#506]
public void testArrayIndexForExceptions() throws Exception
{
final String OBJECTS_JSON = "[ \"KEY2\", false ]";
try {
MAPPER.readValue(OBJECTS_JSON, Key[].class);
fail("Should not pass");
} catch (JsonMappingException e) {
verifyException(e, "Can not deserialize");
List<JsonMappingException.Reference> refs = e.getPath();
assertEquals(1, refs.size());
assertEquals(1, refs.get(0).getIndex());
}
try {
MAPPER.readValue("[ \"xyz\", { } ]", String[].class);
fail("Should not pass");
} catch (JsonMappingException e) {
verifyException(e, "Can not deserialize");
List<JsonMappingException.Reference> refs = e.getPath();
assertEquals(1, refs.size());
assertEquals(1, refs.get(0).getIndex());
}
try {
MAPPER.readValue("{\"keys\":"+OBJECTS_JSON+"}", KeyListBean.class);
fail("Should not pass");
} catch (JsonMappingException e) {
verifyException(e, "Can not deserialize");
List<JsonMappingException.Reference> refs = e.getPath();
assertEquals(2, refs.size());
// Bean has no index, but has name:
assertEquals(-1, refs.get(0).getIndex());
assertEquals("keys", refs.get(0).getFieldName());
// and for List, reverse:
assertEquals(1, refs.get(1).getIndex());
assertNull(refs.get(1).getFieldName());
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> associated schema.
*
* @since 2.2
*/
public boolean isRequired();
/**
* Method for finding annotation associated with this property;
* meaning annotation associated with one of entities used to
* access property.
*/
public <A extends Annotation> A getAnnotation(Class<A> acls);
/**
* Method for finding annotation associated with context of
* this property; usually class in which member is declared
* (or its subtype if processing subtype).
*/
public <A extends Annotation> A getContextAnnotation(Class<A> acls);
/**
* Method for accessing primary physical entity that represents the property;
* annotated field, method or constructor property.
*/
public AnnotatedMember getMember();
/**
* Method that can be called to visit the type structure that this
* property is part of.
* Note that not all implementations support traversal with this
* method; those that do not should throw
* {@link UnsupportedOperationException}.
*
* @param objectVisitor Visitor to used as the callback handler
*
* @since 2.2
*/
public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor)
throws JsonMappingException;
/*
/**********************************************************
/* Helper classes
/**********************************************************
*/
/**
* Simple stand-alone implementation, useful as a placeholder
* or base class for more complex implementations.
*/
public static class Std implements BeanProperty
{
protected final PropertyName _name;
protected final JavaType _type;
protected final PropertyName _wrapperName;
protected final PropertyMetadata _metadata;
/**
* Physical entity (field, method or constructor argument) that
* is used to access value of property (or in case of constructor
* property, just placeholder)
*/
protected final AnnotatedMember _member;
/**
* Annotations defined in the context class (if any); may be null
* if no annotations were found
*/
protected final Annotations _contextAnnotations;
public Std(PropertyName name, JavaType type, PropertyName wrapperName,
Annotations contextAnnotations, AnnotatedMember member,
PropertyMetadata metadata)
{
_name = name;
_type = type;
_wrapperName = wrapperName;
_metadata = metadata;
_member = member;
_contextAnnotations = contextAnnotations;
}
@Deprecated // since 2.3
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> no view has been set.
*/
public abstract Class<?> getActiveView();
/*
/**********************************************************
/* Generic attributes (2.3+)
/**********************************************************
*/
/**
* Method for accessing attributes available in this context.
* Per-call attributes have highest precedence; attributes set
* via {@link ObjectReader} or {@link ObjectWriter} have lower
* precedence.
*
* @param key Key of the attribute to get
* @return Value of the attribute, if any; null otherwise
*
* @since 2.3
*/
public abstract Object getAttribute(Object key);
/**
* Method for setting per-call value of given attribute.
* This will override any previously defined value for the
* attribute within this context.
*
* @param key Key of the attribute to set
* @param value Value to set attribute to
*
* @return This context object, to allow chaining
*
* @since 2.3
*/
public abstract DatabindContext setAttribute(Object key, Object value);
/*
/**********************************************************
/* Type instantiation/resolution
/**********************************************************
*/
/**
* Convenience method for constructing {@link JavaType} for given JDK
* type (usually {@link java.lang.Class})
*/
public JavaType constructType(Type type) {
return getTypeFactory().constructType(type);
}
/**
* Convenience method for constructing subtypes, retaining generic
* type parameter (if any)
*/
public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) {
// simple optimization to avoid costly introspection if type-erased type does NOT differ
if (baseType.getRawClass() == subclass) {
return baseType;
}
return getConfig().constructSpecializedType(baseType, subclass);
}
public abstract TypeFactory getTypeFactory();
/*
/**********************************************************
/* Helper object construction
/**********************************************************
*/
public ObjectIdGenerator<?> objectIdGeneratorInstance(Annotated annotated,
ObjectIdInfo objectIdInfo)
throws JsonMappingException
{
Class<?> implClass = objectIdInfo.getGeneratorType();
final MapperConfig<?> config = getConfig();
HandlerInstantiator hi = config.getHandlerInstantiator();
ObjectIdGenerator<?> gen = (hi == null) ? null : hi.objectIdGeneratorInstance(config,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> annotated, implClass);
if (gen == null) {
gen = (ObjectIdGenerator<?>) ClassUtil.createInstance(implClass,
config.canOverrideAccessModifiers());
}
return gen.forScope(objectIdInfo.getScope());
}
public ObjectIdResolver objectIdResolverInstance(Annotated annotated, ObjectIdInfo objectIdInfo)
{
Class<? extends ObjectIdResolver> implClass = objectIdInfo.getResolverType();
final MapperConfig<?> config = getConfig();
HandlerInstantiator hi = config.getHandlerInstantiator();
ObjectIdResolver resolver = (hi == null) ? null : hi.resolverIdGeneratorInstance(config, annotated, implClass);
if (resolver == null) {
resolver = ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers());
}
return resolver;
}
/**
* Helper method to use to construct a {@link Converter}, given a definition
* that may be either actual converter instance, or Class for instantiating one.
*
* @since 2.2
*/
@SuppressWarnings("unchecked")
public Converter<Object,Object> converterInstance(Annotated annotated,
Object converterDef)
throws JsonMappingException
{
if (converterDef == null) {
return null;
}
if (converterDef instanceof Converter<?,?>) {
return (Converter<Object,Object>) converterDef;
}
if (!(converterDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned Converter definition of type "
+converterDef.getClass().getName()+"; expected type Converter or Class<Converter> instead");
}
Class<?> converterClass = (Class<?>)converterDef;
// there are some known "no class" markers to consider too:
if (converterClass == Converter.None.class || ClassUtil.isBogusClass(converterClass)) {
return null;
}
if (!Converter.class.isAssignableFrom(converterClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "
+converterClass.getName()+"; expected Class<Converter>");
}
final MapperConfig<?> config = getConfig();
HandlerInstantiator hi = config.getHandlerInstantiator();
Converter<?,?> conv = (hi == null) ? null : hi.converterInstance(config, annotated, converterClass);
if (conv == null) {
conv = (Converter<?,?>) ClassUtil.create
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> not need JSON
* Array or Object start/end markers), and then write type suffix.
* This should work for most cases; some sub-classes may want to
* change this behavior.
*/
@Override
public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonGenerationException
{
typeSer.writeTypePrefixForScalar(value, jgen);
serialize(value, jgen, provider);
typeSer.writeTypeSuffixForScalar(value, jgen);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
if (visitor != null) {
visitor.expectStringFormat(typeHint);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> jp, DeserializationContext ctxt, Object instance)
throws IOException, JsonProcessingException
{
deserializeSetAndReturn(jp, ctxt, instance);
}
@Override
public Object deserializeSetAndReturn(JsonParser jp, DeserializationContext ctxt, Object instance)
throws IOException, JsonProcessingException
{
boolean usingIdentityInfo = _objectIdInfo != null || _valueDeserializer.getObjectIdReader() != null;
try {
return setAndReturn(instance, deserialize(jp, ctxt));
} catch (UnresolvedForwardReference reference) {
if (!usingIdentityInfo) {
throw JsonMappingException.from(jp, "Unresolved forward reference but no identity info.", reference);
}
reference.getRoid().appendReferring(new PropertyReferring(this, reference, _type.getRawClass(), instance));
return null;
}
}
@Override
public void set(Object instance, Object value) throws IOException {
_forward.set(instance, value);
}
@Override
public Object setAndReturn(Object instance, Object value) throws IOException {
return _forward.setAndReturn(instance, value);
}
public final static class PropertyReferring extends Referring {
private final ObjectIdReferenceProperty _parent;
public final Object _pojo;
public PropertyReferring(ObjectIdReferenceProperty parent,
UnresolvedForwardReference ref, Class<?> type, Object ob)
{
super(ref, type);
_parent = parent;
_pojo = ob;
}
@Override
public void handleResolvedForwardReference(Object id, Object value) throws IOException
{
if (!hasId(id)) {
throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id
+ "] that wasn't previously seen as unresolved.");
}
_parent.set(_pojo, value);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> null);
_elementType = elemType;
_staticTyping = staticTyping;
_valueTypeSerializer = vts;
_dynamicSerializers = PropertySerializerMap.emptyMap();
_elementSerializer = elementSerializer;
}
public ObjectArraySerializer(ObjectArraySerializer src, TypeSerializer vts)
{
super(src);
_elementType = src._elementType;
_valueTypeSerializer = vts;
_staticTyping = src._staticTyping;
_dynamicSerializers = src._dynamicSerializers;
_elementSerializer = src._elementSerializer;
}
@SuppressWarnings("unchecked")
public ObjectArraySerializer(ObjectArraySerializer src,
BeanProperty property, TypeSerializer vts, JsonSerializer<?> elementSerializer)
{
super(src, property);
_elementType = src._elementType;
_valueTypeSerializer = vts;
_staticTyping = src._staticTyping;
_dynamicSerializers = src._dynamicSerializers;
_elementSerializer = (JsonSerializer<Object>) elementSerializer;
}
@Override
public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts)
{
return new ObjectArraySerializer(_elementType, _staticTyping, vts, _elementSerializer);
}
public ObjectArraySerializer withResolved(BeanProperty prop,
TypeSerializer vts, JsonSerializer<?> ser) {
if (_property == prop && ser == _elementSerializer && _valueTypeSerializer == vts) {
return this;
}
return new ObjectArraySerializer(this, prop, vts, ser);
}
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
TypeSerializer vts = _valueTypeSerializer;
if (vts != null) {
vts = vts.forProperty(property);
}
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
* checking here since we finally know for sure the property,
* and it may have overrides
*/
JsonSerializer<?> ser = null;
// First: if we have a property, may have property-annotation overrides
if (property != null) {
AnnotatedMember m = property.getMember();
if (m != null) {
Object serDef =
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> continue;
}
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
// To fix [JACKSON-508]
if (_elementType.hasGenericTypes()) {
serializer = _findAndAddDynamic(serializers,
provider.constructSpecializedType(_elementType, cc), provider);
} else {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
}
serializer.serialize(elem, jgen, provider);
}
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that gets
* hidden within an InvocationTargetException...
*/
Throwable t = e;
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) {
throw (Error) t;
}
throw JsonMappingException.wrapWithPath(t, elem, i);
}
}
public void serializeContentsUsing(Object[] value, JsonGenerator jgen, SerializerProvider provider,
JsonSerializer<Object> ser)
throws IOException, JsonGenerationException
{
final int len = value.length;
final TypeSerializer typeSer = _valueTypeSerializer;
int i = 0;
Object elem = null;
try {
for (; i < len; ++i) {
elem = value[i];
if (elem == null) {
provider.defaultSerializeNull(jgen);
continue;
}
if (typeSer == null) {
ser.serialize(elem, jgen, provider);
} else {
ser.serializeWithType(elem, jgen, provider, typeSer);
}
}
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) {
throw (Error) t;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> throw JsonMappingException.wrapWithPath(t, elem, i);
}
}
public void serializeTypedContents(Object[] value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
final int len = value.length;
final TypeSerializer typeSer = _valueTypeSerializer;
int i = 0;
Object elem = null;
try {
PropertySerializerMap serializers = _dynamicSerializers;
for (; i < len; ++i) {
elem = value[i];
if (elem == null) {
provider.defaultSerializeNull(jgen);
continue;
}
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
serializer.serializeWithType(elem, jgen, provider, typeSer);
}
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
if (t instanceof Error) {
throw (Error) t;
}
throw JsonMappingException.wrapWithPath(t, elem, i);
}
}
@SuppressWarnings("deprecation")
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
ObjectNode o = createSchemaNode("array", true);
if (typeHint != null) {
JavaType javaType = provider.constructType(typeHint);
if (javaType.isArrayType()) {
Class<?> componentType = ((ArrayType) javaType).getContentType().getRawClass();
// 15-Oct-2010, tatu: We can't serialize plain Object.class; but what should it produce here? Untyped?
if (componentType == Object.class) {
o.put("items", com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode());
} else {
JsonSerializer<Object> ser = provider.findValueSerializer(componentType, _property);
JsonNode schemaNode = (ser instanceof SchemaAware) ?
((SchemaAware) ser).getSchema(provider, null) :
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
o.put("items", schemaNode);
}
}
}
return o;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonArrayFormatVisitor arrayVisitor = visitor.expectArrayFormat(typeHint);
if (arrayVisitor != null) {
TypeFactory tf = visitor.getProvider().getTypeFactory();
JavaType contentType = tf.moreSpecificType(_elementType, typeHint.getContentType());
if (contentType == null) {
throw new JsonMappingException("Could not resolve type");
}
JsonSerializer<?> valueSer = _elementSerializer;
if (valueSer == null) {
valueSer = visitor.getProvider().findValueSerializer(contentType, _property);
}
arrayVisitor.itemsFormat(valueSer, contentType);
}
}
protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
// did we get a new map of serializers? If so, start using it
if (map != result.map) {
_dynamicSerializers = result.map;
}
return result.serializer;
}
protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
JavaType type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
// did we get a new map of serializers? If so, start using it
if (map != result.map) {
_dynamicSerializers = result.map;
}
return result.serializer;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Type;
protected Base(Class<T> cls, JsonParser.NumberType numberType, String schemaType) {
super(cls);
_numberType = numberType;
_schemaType = schemaType;
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode(_schemaType, true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
if (v2 != null) {
v2.numberType(_numberType);
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov,
BeanProperty property) throws JsonMappingException
{
if (property != null) {
JsonFormat.Value format = prov.getAnnotationIntrospector().findFormat(property.getMember());
if (format != null) {
switch (format.getShape()) {
case STRING:
return ToStringSerializer.instance;
default:
}
}
}
return this;
}
}
/*
/**********************************************************
/* Concrete serializers, numerics
/**********************************************************
*/
@JacksonStdImpl
public final static class ShortSerializer extends Base<Short>
{
final static ShortSerializer instance = new ShortSerializer();
public ShortSerializer() { super(Short.class, JsonParser.NumberType.INT, "number"); }
@Override
public void serialize(Short value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeNumber(value.shortValue());
}
}
/**
* This is the special serializer for regular {@link java.lang.Integer}s
* (and primitive ints)
*<p>
* Since this is one of "native" types, no type information is ever
* included on serialization (unlike for most scalar types as of 1.5)
*/
@JacksonStdImpl
public final static class IntegerSerializer extends Base<Integer>
{
public IntegerSerializer() { super(Integer.class, JsonParser.NumberType.INT ,"integer"); }
@Override
public void serialize(Integer value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeNumber(value.intValue());
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, String encoding)
throws IOException, JsonParseException
{
/* 23-Apr-2008, tatus: UTF-32 is not supported by JDK, have to
* use our own codec too (which is not optimal since there's
* a chance both encoder and decoder might have bugs, but ones
* that cancel each other out or such)
*/
byte[] data;
if (encoding.equalsIgnoreCase("UTF-32")) {
data = encodeInUTF32BE(input);
} else {
data = input.getBytes(encoding);
}
InputStream is = new ByteArrayInputStream(data);
return f.createParser(is);
}
/*
/**********************************************************
/* Additional assertion methods
/**********************************************************
*/
protected void assertToken(JsonToken expToken, JsonToken actToken)
{
if (actToken != expToken) {
fail("Expected token "+expToken+", current token "+actToken);
}
}
protected void assertToken(JsonToken expToken, JsonParser jp)
{
assertToken(expToken, jp.getCurrentToken());
}
protected void assertType(Object ob, Class<?> expType)
{
if (ob == null) {
fail("Expected an object of type "+expType.getName()+", got null");
}
Class<?> cls = ob.getClass();
if (!expType.isAssignableFrom(cls)) {
fail("Expected type "+expType.getName()+", got "+cls.getName());
}
}
protected void assertValidLocation(JsonLocation location) {
assertNotNull("Should have non-null location", location);
assertTrue("Should have positive line number", location.getLineNr() > 0);
}
protected void verifyException(Throwable e, String... matches)
{
String msg = e.getMessage();
String lmsg = (msg == null) ? "" : msg.toLowerCase();
for (String match : matches) {
String lmatch = match.toLowerCase();
if (lmsg.indexOf(lmatch) >= 0) {
return;
}
}
fail("Expected an exception with one of substrings ("+Arrays.asList(matches)+"): got one with message \""+msg+"\"");
}
/**
* Method that gets textual contents of the current token using
* available methods, and ensures results
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
public class StackTraceElementDeserializer
extends StdScalarDeserializer<StackTraceElement>
{
private static final long serialVersionUID = 1L;
public StackTraceElementDeserializer() { super(StackTraceElement.class); }
@Override
public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
JsonToken t = jp.getCurrentToken();
// Must get an Object
if (t == JsonToken.START_OBJECT) {
String className = "", methodName = "", fileName = "";
int lineNumber = -1;
while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
String propName = jp.getCurrentName();
if ("className".equals(propName)) {
className = jp.getText();
} else if ("fileName".equals(propName)) {
fileName = jp.getText();
} else if ("lineNumber".equals(propName)) {
if (t.isNumeric()) {
lineNumber = jp.getIntValue();
} else {
throw JsonMappingException.from(jp, "Non-numeric token ("+t+") for property 'lineNumber'");
}
} else if ("methodName".equals(propName)) {
methodName = jp.getText();
} else if ("nativeMethod".equals(propName)) {
// no setter, not passed via constructor: ignore
} else {
handleUnknownProperty(jp, ctxt, _valueClass, propName);
}
}
return new StackTraceElement(className, methodName, fileName, lineNumber);
} else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
jp.nextToken();
final StackTraceElement value = deserialize(jp, ctxt);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>**
*/
protected JsonDeserializer<Object> _mapDeserializer;
protected JsonDeserializer<Object> _listDeserializer;
protected JsonDeserializer<Object> _stringDeserializer;
protected JsonDeserializer<Object> _numberDeserializer;
public UntypedObjectDeserializer() {
super(Object.class);
}
@SuppressWarnings("unchecked")
public UntypedObjectDeserializer(UntypedObjectDeserializer base,
JsonDeserializer<?> mapDeser, JsonDeserializer<?> listDeser,
JsonDeserializer<?> stringDeser, JsonDeserializer<?> numberDeser)
{
super(Object.class);
_mapDeserializer = (JsonDeserializer<Object>) mapDeser;
_listDeserializer = (JsonDeserializer<Object>) listDeser;
_stringDeserializer = (JsonDeserializer<Object>) stringDeser;
_numberDeserializer = (JsonDeserializer<Object>) numberDeser;
}
/*
/**********************************************************
/* Initialization
/**********************************************************
*/
/**
* We need to implement this method to properly find things to delegate
* to: it can not be done earlier since delegated deserializers almost
* certainly require access to this instance (at least "List" and "Map" ones)
*/
@Override
public void resolve(DeserializationContext ctxt) throws JsonMappingException
{
JavaType obType = ctxt.constructType(Object.class);
JavaType stringType = ctxt.constructType(String.class);
TypeFactory tf = ctxt.getTypeFactory();
_mapDeserializer = _findCustomDeser(ctxt, tf.constructMapType(Map.class, stringType, obType));
_listDeserializer = _findCustomDeser(ctxt, tf.constructCollectionType(List.class, obType));
_stringDeserializer = _findCustomDeser(ctxt, stringType);
_numberDeserializer = _findCustomDeser(ctxt, tf.constructType(Number.class));
}
@SuppressWarnings("unchecked")
protected JsonDeserializer<Object> _findCustomDeser(DeserializationContext ctxt, JavaType type)
throws JsonMappingException
{
// NOTE: since we don't yet have the referring property, this should be fine:
JsonDeserializer<?> deser = ctxt.findRootValueDeserializer(type);
if (ClassUtil.isJacksonStdImpl(deser)) {
return null;
}
return (JsonDeserializer<Object>) deser;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> @Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
// 20-Apr-2014, tatu: If nothing custom, let's use "vanilla" instance,
// simpler and can avoid some of delegation
if ((_stringDeserializer == null) && (_numberDeserializer == null)
&& (_mapDeserializer == null) && (_listDeserializer == null)
&& getClass() == UntypedObjectDeserializer.class) {
return Vanilla.std;
}
JsonDeserializer<?> mapDeserializer = _mapDeserializer;
if (mapDeserializer instanceof ContextualDeserializer) {
mapDeserializer = ((ContextualDeserializer)mapDeserializer).createContextual(ctxt, property);
}
JsonDeserializer<?> listDeserializer = _listDeserializer;
if (listDeserializer instanceof ContextualDeserializer) {
listDeserializer = ((ContextualDeserializer)listDeserializer).createContextual(ctxt, property);
}
JsonDeserializer<?> stringDeserializer = _stringDeserializer;
if (stringDeserializer instanceof ContextualDeserializer) {
stringDeserializer = ((ContextualDeserializer)stringDeserializer).createContextual(ctxt, property);
}
JsonDeserializer<?> numberDeserializer = _numberDeserializer;
if (numberDeserializer instanceof ContextualDeserializer) {
numberDeserializer = ((ContextualDeserializer)numberDeserializer).createContextual(ctxt, property);
}
// And if anything changed, we'll need to change too!
if ((mapDeserializer != _mapDeserializer)
|| (listDeserializer != _listDeserializer)
|| (stringDeserializer != _stringDeserializer)
|| (numberDeserializer != _numberDeserializer)
) {
return _withResolved(mapDeserializer, listDeserializer,
stringDeserializer, numberDeserializer);
}
return this;
}
protected JsonDeserializer<?> _withResolved(JsonDeserializer<?> mapDeser,
JsonDeserializer<?> listDeser,
JsonDeserializer<?> stringDeser, JsonDeserializer<?> numberDeser) {
return new UntypedObjectDeserializer(this,
mapDeser, listDeser, stringDeser, numberDeser);
}
/*
/**********************************************************
/* Deserializer API
/**********************************************************
*/
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
switch (jp.getCurrentToken()) {
case FIELD_NAME:
case START_OBJECT:
if
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> if (f == null) {
throw new IllegalArgumentException("No Field passed for property '"+src.getName()
+"' (class "+src.getDeclaringClass().getName()+")");
}
_field = f;
}
@Override
public FieldProperty withName(PropertyName newName) {
return new FieldProperty(this, newName);
}
@Override
public FieldProperty withValueDeserializer(JsonDeserializer<?> deser) {
return new FieldProperty(this, deser);
}
/*
/**********************************************************
/* BeanProperty impl
/**********************************************************
*/
@Override
public <A extends Annotation> A getAnnotation(Class<A> acls) {
return _annotated.getAnnotation(acls);
}
@Override public AnnotatedMember getMember() { return _annotated; }
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public void deserializeAndSet(JsonParser jp,
DeserializationContext ctxt, Object instance)
throws IOException, JsonProcessingException
{
set(instance, deserialize(jp, ctxt));
}
@Override
public Object deserializeSetAndReturn(JsonParser jp,
DeserializationContext ctxt, Object instance)
throws IOException, JsonProcessingException
{
return setAndReturn(instance, deserialize(jp, ctxt));
}
@Override
public final void set(Object instance, Object value)
throws IOException
{
try {
_field.set(instance, value);
} catch (Exception e) {
_throwAsIOE(e, value);
}
}
@Override
public Object setAndReturn(Object instance, Object value)
throws IOException
{
try {
_field.set(instance, value);
} catch (Exception e) {
_throwAsIOE(e, value);
}
return instance;
}
/*
/**********************************************************
/* JDK serialization handling
/**********************************************************
*/
Object readResolve() {
return new FieldProperty(this, _annotated.getAnnotated());
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.impl;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
import com.fasterxml.jackson.databind.ser.*;
public class PropertyBasedObjectIdGenerator
extends ObjectIdGenerators.PropertyGenerator
{
private static final long serialVersionUID = 1L;
protected final BeanPropertyWriter _property;
public PropertyBasedObjectIdGenerator(ObjectIdInfo oid, BeanPropertyWriter prop)
{
this(oid.getScope(), prop);
}
protected PropertyBasedObjectIdGenerator(Class<?> scope, BeanPropertyWriter prop)
{
super(scope);
_property = prop;
}
/**
* We must override this method, to prevent errors when scopes are the same,
* but underlying class (on which to access property) is different.
*/
@Override
public boolean canUseFor(ObjectIdGenerator<?> gen) {
if (gen.getClass() == getClass()) {
PropertyBasedObjectIdGenerator other = (PropertyBasedObjectIdGenerator) gen;
if (other.getScope() == _scope) {
/* 26-Jul-2012, tatu: This is actually not enough, because the property
* accessor within BeanPropertyWriter won't work for other property fields
* (see [https://github.com/FasterXML/jackson-module-jaxb-annotations/issues/9]
* for details).
* So we need to verify that underlying property is actually the same.
*/
return (other._property == _property);
}
}
return false;
}
@Override
public Object generateId(Object forPojo) {
try {
return _property.get(forPojo);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("Problem accessing property '"
+_property.getName()+"': "+e.getMessage(), e);
}
}
@Override
public ObjectIdGenerator<Object> forScope(Class<?> scope) {
return (scope == _scope) ? this : new PropertyBasedObjectIdGenerator(scope, _property);
}
@Override
public ObjectIdGenerator<Object> newForSerialization(Object context) {
// No state
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> * we'll ignore it...
*/
@Override
public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
return this;
}
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
* checking here since we finally know for sure the property,
* and it may have overrides
*/
JsonSerializer<?> ser = null;
// First: if we have a property, may have property-annotation overrides
if (property != null) {
AnnotatedMember m = property.getMember();
if (m != null) {
Object serDef = provider.getAnnotationIntrospector().findContentSerializer(m);
if (serDef != null) {
ser = provider.serializerInstance(m, serDef);
}
}
}
if (ser == null) {
ser = _elementSerializer;
}
// #124: May have a content converter
ser = findConvertingContentSerializer(provider, property, ser);
if (ser == null) {
ser = provider.findValueSerializer(String.class, property);
} else {
ser = provider.handleSecondaryContextualization(ser, property);
}
// Optimization: default serializer just writes String, so we can avoid a call:
if (isDefaultSerializer(ser)) {
ser = null;
}
// note: will never have TypeSerializer, because Strings are "natural" type
if (ser == _elementSerializer) {
return this;
}
return new StringArraySerializer(this, property, ser);
}
/*
/**********************************************************
/* Simple accessors
/**********************************************************
*/
@Override
public JavaType getContentType() {
return VALUE_TYPE;
}
@Override
public JsonSerializer<?> getContentSerializer() {
return _elementSerializer;
}
@Override
public boolean isEmpty(String[] value) {
return (value == null) || (value.length == 0);
}
@Override
public boolean hasSingleElement(String[] value) {
return (value.length == 1);
}
/*
/
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>**********************************************************
/* Actual serialization
/**********************************************************
*/
@Override
public void serializeContents(String[] value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
final int len = value.length;
if (len == 0) {
return;
}
if (_elementSerializer != null) {
serializeContentsSlow(value, jgen, provider, _elementSerializer);
return;
}
/* 08-Dec-2008, tatus: If we want this to be fully overridable
* (for example, to support String cleanup during writing
* or something), we should find serializer by provider.
* But for now, that seems like an overkill: and caller can
* add custom serializer if that is needed as well.
* (ditto for null values)
*/
//JsonSerializer<String> ser = (JsonSerializer<String>)provider.findValueSerializer(String.class);
for (int i = 0; i < len; ++i) {
String str = value[i];
if (str == null) {
jgen.writeNull();
} else {
//ser.serialize(value[i], jgen, provider);
jgen.writeString(value[i]);
}
}
}
private void serializeContentsSlow(String[] value, JsonGenerator jgen, SerializerProvider provider, JsonSerializer<Object> ser)
throws IOException, JsonGenerationException
{
for (int i = 0, len = value.length; i < len; ++i) {
String str = value[i];
if (str == null) {
provider.defaultSerializeNull(jgen);
} else {
ser.serialize(value[i], jgen, provider);
}
}
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("array", true).set("items", createSchemaNode("string"));
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
if (visitor != null) {
JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
if (v2 != null) {
v2.itemsFormat(JsonFormat
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> /* (mapping from JSON to Java types);
/* main methods
/**********************************************************
*/
/**
* Method to deserialize JSON content into a non-container
* type (it can be an array type, however): typically a bean, array
* or a wrapper type (like {@link java.lang.Boolean}).
*<p>
* Note: this method should NOT be used if the result type is a
* container ({@link java.util.Collection} or {@link java.util.Map}.
* The reason is that due to type erasure, key and value types
* can not be introspected when using this method.
*/
@Override
@SuppressWarnings("unchecked")
public <T> T readValue(JsonParser jp, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), jp, _typeFactory.constructType(valueType));
}
/**
* Method to deserialize JSON content into a Java type, reference
* to which is passed as argument. Type is passed using so-called
* "super type token" (see )
* and specifically needs to be used if the root type is a
* parameterized (generic) container type.
*/
@Override
@SuppressWarnings("unchecked")
public <T> T readValue(JsonParser jp, TypeReference<?> valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), jp, _typeFactory.constructType(valueTypeRef));
}
/**
* Method to deserialize JSON content into a Java type, reference
* to which is passed as argument. Type is passed using
* Jackson specific type; instance of which can be constructed using
* {@link TypeFactory}.
*/
@Override
@SuppressWarnings("unchecked")
public final <T> T readValue(JsonParser jp, ResolvedType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), jp, (JavaType) valueType);
}
/**
* Type-safe overloaded method, basically alias for {@link #readValue(JsonParser, ResolvedType)}.
*/
@SuppressWarnings("unchecked")
public <T> T readValue(JsonParser jp, JavaType valueType)
throws IOException,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> JsonParseException, JsonMappingException
{
return (T) _readValue(getDeserializationConfig(), jp, valueType);
}
/**
* Method to deserialize JSON content as tree expressed
* using set of {@link JsonNode} instances. Returns
* root of the resulting tree (where root can consist
* of just a single node if the current event is a
* value event, not container).
*/
@Override
public <T extends TreeNode> T readTree(JsonParser jp)
throws IOException, JsonProcessingException
{
/* 02-Mar-2009, tatu: One twist; deserialization provider
* will map JSON null straight into Java null. But what
* we want to return is the "null node" instead.
*/
/* 05-Aug-2011, tatu: Also, must check for EOF here before
* calling readValue(), since that'll choke on it otherwise
*/
DeserializationConfig cfg = getDeserializationConfig();
JsonToken t = jp.getCurrentToken();
if (t == null) {
t = jp.nextToken();
if (t == null) {
return null;
}
}
JsonNode n = (JsonNode) _readValue(cfg, jp, JSON_NODE_TYPE);
if (n == null) {
n = getNodeFactory().nullNode();
}
@SuppressWarnings("unchecked")
T result = (T) n;
return result;
}
/**
* Method for reading sequence of Objects from parser stream.
* Sequence can be either root-level "unwrapped" sequence (without surrounding
* JSON array), or a sequence contained in a JSON Array.
* In either case {@link JsonParser} must point to the first token of
* the first element, OR not point to any token (in which case it is advanced
* to the next token). This means, specifically, that for wrapped sequences,
* parser MUST NOT point to the surrounding <code>START_ARRAY</code> but rather
* to the token following it.
*<p>
* Note that {@link ObjectReader} has more complete set of variants.
*/
@Override
public <T> MappingIterator<T> readValues(JsonParser jp, ResolvedType valueType)
throws IOException, JsonProcessingException
{
return readValues(jp,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Node.instance : n;
}
/**
* Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances.
* Returns root of the resulting tree (where root can consist of just a single node if the current
* event is a value event, not container).
*
* @param source URL to use for fetching contents to parse as JSON for building a tree instance
*/
public JsonNode readTree(URL source)
throws IOException, JsonProcessingException
{
JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createParser(source), JSON_NODE_TYPE);
return (n == null) ? NullNode.instance : n;
}
/*
/**********************************************************
/* Public API (from ObjectCodec): serialization
/* (mapping from Java types to Json)
/**********************************************************
*/
/**
* Method that can be used to serialize any Java value as
* JSON output, using provided {@link JsonGenerator}.
*/
@Override
public void writeValue(JsonGenerator jgen, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
SerializationConfig config = getSerializationConfig();
// 10-Aug-2012, tatu: as per [Issue#12], must handle indentation:
if (config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
jgen.useDefaultPrettyPrinter();
}
if (config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
_writeCloseableValue(jgen, value, config);
} else {
_serializerProvider(config).serializeValue(jgen, value);
if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
jgen.flush();
}
}
}
/*
/**********************************************************
/* Public API (from TreeCodec via ObjectCodec): Tree Model support
/**********************************************************
*/
@Override
public void writeTree(JsonGenerator jgen, TreeNode rootNode)
throws IOException, JsonProcessingException
{
SerializationConfig config = getSerializationConfig();
_serializerProvider(config).serializeValue(jgen, rootNode);
if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
jgen.flush();
}
}
/**
* Method to serialize given JSON Tree, using generator
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> catch (JsonProcessingException e) {
throw e;
} catch (IOException e) { // should not occur, no real i/o...
throw new IllegalArgumentException(e.getMessage(), e);
}
}
/**
* Reverse of {@link #treeToValue}; given a value (usually bean), will
* construct equivalent JSON Tree representation. Functionally similar
* to serializing value into JSON and parsing JSON as tree, but
* more efficient.
*<p>
* NOTE: one known difference from actual serialization is that so-called
* "raw values" are not supported -- since they are opaque sequence of
* bytes to include (which may or may not be supported by the backend)
* they can not be converted using this method. It may be possible to
* support conversions using full serialization, if raw values must be
* preserved.
*
* @param <T> Actual node type; usually either basic {@link JsonNode} or
* {@link com.fasterxml.jackson.databind.node.ObjectNode}
* @param fromValue Bean value to convert
* @return Root node of the resulting JSON tree
*/
@SuppressWarnings({ "unchecked", "resource" })
public <T extends JsonNode> T valueToTree(Object fromValue)
throws IllegalArgumentException
{
if (fromValue == null) return null;
TokenBuffer buf = new TokenBuffer(this, false);
JsonNode result;
try {
writeValue(buf, fromValue);
JsonParser jp = buf.asParser();
result = readTree(jp);
jp.close();
} catch (IOException e) { // should not occur, no real i/o...
throw new IllegalArgumentException(e.getMessage(), e);
}
return (T) result;
}
/*
/**********************************************************
/* Extended Public API, accessors
/**********************************************************
*/
/**
* Method that can be called to check whether mapper thinks
* it could serialize an instance of given Class.
* Check is done
* by checking whether a serializer can be found for the type.
*<p>
* NOTE: since this method does NOT throw exceptions, but internal
* processing may, caller usually has little information as to why
* serialization would fail.
*
* @return True if mapper can find a serializer for instances of
* given class (potentially serial
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>izable), false otherwise (not
* serializable)
*/
public boolean canSerialize(Class<?> type) {
return _serializerProvider(getSerializationConfig()).hasSerializerFor(type, null);
}
/**
* Method similar to {@link #canSerialize(Class)} but that can return
* actual {@link Throwable} that was thrown when trying to construct
* serializer: this may be useful in figuring out what the actual problem is.
*
* @since 2.3
*/
public boolean canSerialize(Class<?> type, AtomicReference<Throwable> cause) {
return _serializerProvider(getSerializationConfig()).hasSerializerFor(type, cause);
}
/**
* Method that can be called to check whether mapper thinks
* it could deserialize an Object of given type.
* Check is done
* by checking whether a deserializer can be found for the type.
*
* @return True if mapper can find a serializer for instances of
* given class (potentially serializable), false otherwise (not
* serializable)
*/
public boolean canDeserialize(JavaType type)
{
return createDeserializationContext(null,
getDeserializationConfig()).hasValueDeserializerFor(type, null);
}
/**
* Method similar to {@link #canDeserialize(JavaType)} but that can return
* actual {@link Throwable} that was thrown when trying to construct
* serializer: this may be useful in figuring out what the actual problem is.
*
* @since 2.3
*/
public boolean canDeserialize(JavaType type, AtomicReference<Throwable> cause)
{
return createDeserializationContext(null,
getDeserializationConfig()).hasValueDeserializerFor(type, cause);
}
/*
/**********************************************************
/* Extended Public API, deserialization,
/* convenience methods
/**********************************************************
*/
@SuppressWarnings("unchecked")
public <T> T readValue(File src, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(File src, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T readValue(File src, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
}
@SuppressWarnings("unchecked")
public <T> T readValue(URL src, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(URL src, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T readValue(URL src, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
}
@SuppressWarnings("unchecked")
public <T> T readValue(String content, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(String content, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T readValue(String content, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(content), valueType);
}
@SuppressWarnings("unchecked")
public <T> T readValue(Reader src, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(Reader src, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T readValue(Reader src, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
}
@SuppressWarnings("unchecked")
public <T> T readValue(InputStream src, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(InputStream src, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T readValue(InputStream src, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
}
@SuppressWarnings("unchecked")
public <T> T readValue(byte[] src, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createParser(src
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>), _typeFactory.constructType(valueType));
}
@SuppressWarnings("unchecked")
public <T> T readValue(byte[] src, int offset, int len,
Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueType));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(byte[] src, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(byte[] src, int offset, int len,
TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueTypeRef));
}
@SuppressWarnings("unchecked")
public <T> T readValue(byte[] src, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
}
@SuppressWarnings("unchecked")
public <T> T readValue(byte[] src, int offset, int len,
JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), valueType);
}
/*
/**********************************************************
/* Extended Public API: serialization
/* (mapping from Java types to JSON)
/**********************************************************
*/
/**
* Method that can be used to serialize any Java value as
* JSON output, written to File provided.
*/
public void writeValue(File resultFile, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
_configAndWriteValue(_jsonFactory.createGenerator(resultFile, JsonEncoding.UTF8), value);
}
/**
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> * Method that can be used to serialize any Java value as
* JSON output, using output stream provided (using encoding
* {@link JsonEncoding#UTF8}).
*<p>
* Note: method does not close the underlying stream explicitly
* here; however, {@link JsonFactory} this mapper uses may choose
* to close the stream depending on its settings (by default,
* it will try to close it when {@link JsonGenerator} we construct
* is closed).
*/
public void writeValue(OutputStream out, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
_configAndWriteValue(_jsonFactory.createGenerator(out, JsonEncoding.UTF8), value);
}
/**
* Method that can be used to serialize any Java value as
* JSON output, using Writer provided.
*<p>
* Note: method does not close the underlying stream explicitly
* here; however, {@link JsonFactory} this mapper uses may choose
* to close the stream depending on its settings (by default,
* it will try to close it when {@link JsonGenerator} we construct
* is closed).
*/
public void writeValue(Writer w, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
_configAndWriteValue(_jsonFactory.createGenerator(w), value);
}
/**
* Method that can be used to serialize any Java value as
* a String. Functionally equivalent to calling
* {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter}
* and constructing String, but more efficient.
*<p>
* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
*/
@SuppressWarnings("resource")
public String writeValueAsString(Object value)
throws JsonProcessingException
{
// alas, we have to pull the recycler directly here...
SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
try {
_configAndWriteValue(_jsonFactory.createGenerator(sw), value);
} catch (JsonProcessingException e) { // to support [JACKSON-758]
throw e;
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
throw JsonMappingException
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.fromUnexpectedIOE(e);
}
return sw.getAndClear();
}
/**
* Method that can be used to serialize any Java value as
* a byte array. Functionally equivalent to calling
* {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream}
* and getting bytes, but more efficient.
* Encoding used will be UTF-8.
*<p>
* Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it.
*/
@SuppressWarnings("resource")
public byte[] writeValueAsBytes(Object value)
throws JsonProcessingException
{
ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler());
try {
_configAndWriteValue(_jsonFactory.createGenerator(bb, JsonEncoding.UTF8), value);
} catch (JsonProcessingException e) { // to support [JACKSON-758]
throw e;
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
throw JsonMappingException.fromUnexpectedIOE(e);
}
byte[] result = bb.toByteArray();
bb.release();
return result;
}
/*
/**********************************************************
/* Extended Public API: constructing ObjectWriters
/* for more advanced configuration
/**********************************************************
*/
/**
* Convenience method for constructing {@link ObjectWriter}
* with default settings.
*/
public ObjectWriter writer() {
return new ObjectWriter(this, getSerializationConfig());
}
/**
* Factory method for constructing {@link ObjectWriter} with
* specified feature enabled (compared to settings that this
* mapper instance has).
*/
public ObjectWriter writer(SerializationFeature feature) {
return new ObjectWriter(this, getSerializationConfig().with(feature));
}
/**
* Factory method for constructing {@link ObjectWriter} with
* specified features enabled (compared to settings that this
* mapper instance has).
*/
public ObjectWriter writer(SerializationFeature first,
SerializationFeature... other) {
return new ObjectWriter(this, getSerializationConfig().with(first, other));
}
/**
* Factory method for constructing {@link ObjectWriter} that will
* serialize objects using specified {@link DateFormat}; or, if
* null passed, using timestamp
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> if (targetType != Object.class
&& !toValueType.hasGenericTypes()
&& targetType.isAssignableFrom(fromValue.getClass())) {
return fromValue;
}
/* Then use TokenBuffer, which is a JsonGenerator:
* (see [JACKSON-175])
*/
TokenBuffer buf = new TokenBuffer(this, false);
try {
// inlined 'writeValue' with minor changes:
// first: disable wrapping when writing
SerializationConfig config = getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE);
// no need to check for closing of TokenBuffer
_serializerProvider(config).serializeValue(buf, fromValue);
// then matching read, inlined 'readValue' with minor mods:
final JsonParser jp = buf.asParser();
Object result;
// ok to pass in existing feature flags; unwrapping handled by mapper
final DeserializationConfig deserConfig = getDeserializationConfig();
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
DeserializationContext ctxt = createDeserializationContext(jp, deserConfig);
result = _findRootDeserializer(ctxt, toValueType).getNullValue();
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else { // pointing to event other than null
DeserializationContext ctxt = createDeserializationContext(jp, deserConfig);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, toValueType);
// note: no handling of unwarpping
result = deser.deserialize(jp, ctxt);
}
jp.close();
return result;
} catch (IOException e) { // should not occur, no real i/o...
throw new IllegalArgumentException(e.getMessage(), e);
}
}
/*
/**********************************************************
/* Extended Public API: JSON Schema generation
/**********************************************************
*/
/**
* Generate <a href="http://json-schema.org/">Json-schema</a>
* instance for specified class.
*
* @param t The class to generate schema for
* @return Constructed JSON schema.
*/
@SuppressWarnings("deprecation")
public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class<?> t)
throws JsonMappingException {
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
return _serializerProvider(getSerializationConfig()).generateJsonSchema(t);
}
/**
* Method for visiting type hierarchy for given type, using specified visitor.
*<p>
* This method can be used for things like
* generating <a href="http://json-schema.org/">Json Schema</a>
* instance for specified type.
*
* @param type Type to generate schema for (possibly with generic signature)
*
* @since 2.1
*/
public void acceptJsonFormatVisitor(Class<?> type, JsonFormatVisitorWrapper visitor)
throws JsonMappingException
{
acceptJsonFormatVisitor(_typeFactory.constructType(type), visitor);
}
/**
* Method for visiting type hierarchy for given type, using specified visitor.
* Visitation uses <code>Serializer</code> hierarchy and related properties
*<p>
* This method can be used for things like
* generating <a href="http://json-schema.org/">Json Schema</a>
* instance for specified type.
*
* @param type Type to generate schema for (possibly with generic signature)
*
* @since 2.1
*/
public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor)
throws JsonMappingException
{
if (type == null) {
throw new IllegalArgumentException("type must be provided");
}
_serializerProvider(getSerializationConfig()).acceptJsonFormatVisitor(type, visitor);
}
/*
/**********************************************************
/* Internal methods for serialization, overridable
/**********************************************************
*/
/**
* Overridable helper method used for constructing
* {@link SerializerProvider} to use for serialization.
*/
protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) {
return _serializerProvider.createInstance(config, _serializerFactory);
}
/**
* Helper method that should return default pretty-printer to
* use for generators constructed by this mapper, when instructed
* to use default pretty printer.
*/
protected PrettyPrinter _defaultPrettyPrinter() {
return _defaultPrettyPrinter;
}
/**
* Method called to configure the generator as necessary and then
* call write functionality
*/
protected final void _configAndWriteValue(JsonGenerator jgen, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
Serialization
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Config cfg = getSerializationConfig();
// [JACKSON-96]: allow enabling pretty printing for ObjectMapper directly
if (cfg.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
jgen.useDefaultPrettyPrinter();
}
// [Issue#232]
if (cfg.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN)) {
jgen.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
}
// [JACKSON-282]: consider Closeable
if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
_configAndWriteCloseable(jgen, value, cfg);
return;
}
boolean closed = false;
try {
_serializerProvider(cfg).serializeValue(jgen, value);
closed = true;
jgen.close();
} finally {
/* won't try to close twice; also, must catch exception (so it
* will not mask exception that is pending)
*/
if (!closed) {
/* 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
* structures, which typically causes more damage.
*/
jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
try {
jgen.close();
} catch (IOException ioe) { }
}
}
}
protected final void _configAndWriteValue(JsonGenerator jgen, Object value, Class<?> viewClass)
throws IOException, JsonGenerationException, JsonMappingException
{
SerializationConfig cfg = getSerializationConfig().withView(viewClass);
if (cfg.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
jgen.useDefaultPrettyPrinter();
}
// [Issue#232]
if (cfg.isEnabled(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN)) {
jgen.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
}
// [JACKSON-282]: consider Closeable
if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
_configAndWriteCloseable(jgen, value, cfg);
return;
}
boolean closed = false;
try {
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> _serializerProvider(cfg).serializeValue(jgen, value);
closed = true;
jgen.close();
} finally {
if (!closed) {
// 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
// structures, which typically causes more damage.
jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
try {
jgen.close();
} catch (IOException ioe) { }
}
}
}
/**
* Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
* method is to be called right after serialization has been called
*/
private final void _configAndWriteCloseable(JsonGenerator jgen, Object value, SerializationConfig cfg)
throws IOException, JsonGenerationException, JsonMappingException
{
Closeable toClose = (Closeable) value;
try {
_serializerProvider(cfg).serializeValue(jgen, value);
JsonGenerator tmpJgen = jgen;
jgen = null;
tmpJgen.close();
Closeable tmpToClose = toClose;
toClose = null;
tmpToClose.close();
} finally {
/* Need to close both generator and value, as long as they haven't yet
* been closed
*/
if (jgen != null) {
// 04-Mar-2014, tatu: But! Let's try to prevent auto-closing of
// structures, which typically causes more damage.
jgen.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
try {
jgen.close();
} catch (IOException ioe) { }
}
if (toClose != null) {
try {
toClose.close();
} catch (IOException ioe) { }
}
}
}
/**
* Helper method used when value to serialize is {@link Closeable} and its <code>close()</code>
* method is to be called right after serialization has been called
*/
private final void _writeCloseableValue(JsonGenerator jgen, Object value, SerializationConfig cfg)
throws IOException, JsonGenerationException, JsonMappingException
{
Closeable toClose = (Closeable) value;
try {
_serializerProvider
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(cfg).serializeValue(jgen, value);
if (cfg.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
jgen.flush();
}
Closeable tmpToClose = toClose;
toClose = null;
tmpToClose.close();
} finally {
if (toClose != null) {
try {
toClose.close();
} catch (IOException ioe) { }
}
}
}
/*
/**********************************************************
/* Internal methods for deserialization, overridable
/**********************************************************
*/
/**
* Internal helper method called to create an instance of {@link DeserializationContext}
* for deserializing a single root value.
* Can be overridden if a custom context is needed.
*/
protected DefaultDeserializationContext createDeserializationContext(JsonParser jp,
DeserializationConfig cfg)
{
return _deserializationContext.createInstance(cfg,
jp, _injectableValues);
}
/**
* Actual implementation of value reading+binding operation.
*/
protected Object _readValue(DeserializationConfig cfg, JsonParser jp, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
/* First: may need to read the next token, to initialize
* state (either before first read from parser, or after
* previous token has been cleared)
*/
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
// [JACKSON-643]: Ask JsonDeserializer what 'null value' to use:
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
result = _findRootDeserializer(ctxt, valueType).getNullValue();
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else { // pointing to event other than null
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
// ok, let's get the value
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
} else {
result = deser.deserialize(jp, ctxt);
}
}
// Need to consume the token
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> too
jp.clearCurrentToken();
return result;
}
protected Object _readMapAndClose(JsonParser jp, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
try {
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
// [JACKSON-643]: Ask JsonDeserializer what 'null value' to use:
DeserializationContext ctxt = createDeserializationContext(jp,
getDeserializationConfig());
result = _findRootDeserializer(ctxt, valueType).getNullValue();
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = null;
} else {
DeserializationConfig cfg = getDeserializationConfig();
DeserializationContext ctxt = createDeserializationContext(jp, cfg);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
} else {
result = deser.deserialize(jp, ctxt);
}
ctxt.checkUnresolvedObjectId();
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
} finally {
try {
jp.close();
} catch (IOException ioe) { }
}
}
/**
* Method called to ensure that given parser is ready for reading
* content for data binding.
*
* @return First token to be used for data binding after this call:
* can never be null as exception will be thrown if parser can not
* provide more tokens.
*
* @throws IOException if the underlying input source has problems during
* parsing
* @throws JsonParseException if parser has problems parsing content
* @throws JsonMappingException if the parser does not have any more
* content to map (note: Json "null" value is considered content;
* enf-of-stream not)
*/
protected JsonToken _initForReading(JsonParser jp)
throws IOException, JsonParseException, JsonMappingException
{
/* First: must point to a token; if not pointing to one, advance.
* This occurs before first read from JsonParser, as well as
* after clearing
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> of current token.
*/
JsonToken t = jp.getCurrentToken();
if (t == null) {
// and then we must get something...
t = jp.nextToken();
if (t == null) {
/* [JACKSON-546] Throw mapping exception, since it's failure to map,
* not an actual parsing problem
*/
throw JsonMappingException.from(jp, "No content to map due to end-of-input");
}
}
return t;
}
protected Object _unwrapAndDeserialize(JsonParser jp, DeserializationContext ctxt,
DeserializationConfig config,
JavaType rootType, JsonDeserializer<Object> deser)
throws IOException, JsonParseException, JsonMappingException
{
String expName = config.getRootName();
if (expName == null) {
PropertyName pname = _rootNames.findRootName(rootType, config);
expName = pname.getSimpleName();
}
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '"
+expName+"'), but "+jp.getCurrentToken());
}
if (jp.nextToken() != JsonToken.FIELD_NAME) {
throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '"
+expName+"'), but "+jp.getCurrentToken());
}
String actualName = jp.getCurrentName();
if (!expName.equals(actualName)) {
throw JsonMappingException.from(jp, "Root name '"+actualName+"' does not match expected ('"
+expName+"') for type "+rootType);
}
// ok, then move to value itself....
jp.nextToken();
Object result = deser.deserialize(jp, ctxt);
// and last, verify that we now get matching END_OBJECT
if (jp.nextToken() != JsonToken.END_OBJECT) {
throw JsonMappingException.from(jp, "Current token not END_OBJECT (to match wrapper object with root name '"
+expName+"'), but "+jp.getCurrentToken());
}
return result;
}
/*
/**********************************************************
/* Internal methods, other
/**********************************************************
*/
/**
* Method called to locate
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> deserializer for the passed root-level value.
*/
protected JsonDeserializer<Object> _findRootDeserializer(DeserializationContext ctxt,
JavaType valueType)
throws JsonMappingException
{
// First: have we already seen it?
JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);
if (deser != null) {
return deser;
}
// Nope: need to ask provider to resolve it
deser = ctxt.findRootValueDeserializer(valueType);
if (deser == null) { // can this happen?
throw new JsonMappingException("Can not find a deserializer for type "+valueType);
}
_rootDeserializers.put(valueType, deser);
return deser;
}
/**
* @since 2.2
*/
protected void _verifySchemaType(FormatSchema schema)
{
if (schema != null) {
if (!_jsonFactory.canUseSchema(schema)) {
throw new IllegalArgumentException("Can not use FormatSchema of type "+schema.getClass().getName()
+" for format "+_jsonFactory.getFormatName());
}
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.jsonFormatVisitors;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Interface {@link com.fasterxml.jackson.databind.JsonSerializer} implements
* to allow for visiting type hierarchy.
*/
public interface JsonFormatVisitable
{
/**
* Get the representation of the schema to which this serializer will conform.
*
* @param typeHint Type of element (entity like property) being visited
*/
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> getConfig().getTimeZone();
*</pre>
*/
public TimeZone getTimeZone() {
return _config.getTimeZone();
}
/*
/**********************************************************
/* Public API, pass-through to DeserializerCache
/**********************************************************
*/
@Deprecated // since 2.3, use overloaded variant
public boolean hasValueDeserializerFor(JavaType type) {
return hasValueDeserializerFor(type, null);
}
/**
* Method for checking whether we could find a deserializer
* for given type.
*
* @param type
* @since 2.3
*/
public boolean hasValueDeserializerFor(JavaType type, AtomicReference<Throwable> cause) {
try {
return _cache.hasValueDeserializerFor(this, _factory, type);
} catch (JsonMappingException e) {
if (cause != null) {
cause.set(e);
}
} catch (RuntimeException e) {
if (cause == null) { // earlier behavior
throw e;
}
cause.set(e);
}
return false;
}
/**
* Method for finding a value deserializer, and creating a contextual
* version if necessary, for value reached via specified property.
*/
@SuppressWarnings("unchecked")
public final JsonDeserializer<Object> findContextualValueDeserializer(JavaType type,
BeanProperty prop) throws JsonMappingException
{
JsonDeserializer<Object> deser = _cache.findValueDeserializer(this, _factory, type);
if (deser != null) {
deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, prop);
}
return deser;
}
/**
* Method for finding a deserializer for root-level value.
*/
@SuppressWarnings("unchecked")
public final JsonDeserializer<Object> findRootValueDeserializer(JavaType type)
throws JsonMappingException
{
JsonDeserializer<Object> deser = _cache.findValueDeserializer(this,
_factory, type);
if (deser == null) { // can this occur?
return null;
}
deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, null);
TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
if (typeDeser != null) {
// important: contextualize to
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> indicate this is for root value
typeDeser = typeDeser.forProperty(null);
return new TypeWrappedDeserializer(typeDeser, deser);
}
return deser;
}
/**
* Convenience method, functionally same as:
*<pre>
* getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
*</pre>
*/
public final KeyDeserializer findKeyDeserializer(JavaType keyType,
BeanProperty prop) throws JsonMappingException {
KeyDeserializer kd = _cache.findKeyDeserializer(this,
_factory, keyType);
// Second: contextualize?
if (kd instanceof ContextualKeyDeserializer) {
kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop);
}
return kd;
}
/*
/**********************************************************
/* Public API, ObjectId handling
/**********************************************************
*/
/**
* Method called to find and return entry corresponding to given
* Object Id: will add an entry if necessary, and never returns null
*/
public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator, ObjectIdResolver resolver);
@Deprecated // since 2.4
public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator);
/**
* Method called to ensure that every object id encounter during processing
* are resolved.
*
* @throws UnresolvedForwardReference
*/
public abstract void checkUnresolvedObjectId()
throws UnresolvedForwardReference;
/*
/**********************************************************
/* Public API, type handling
/**********************************************************
*/
/**
* Convenience method, functionally equivalent to:
*<pre>
* getConfig().constructType(cls);
* </pre>
*/
public final JavaType constructType(Class<?> cls) {
return _config.constructType(cls);
}
/**
* Helper method to use for locating Class for given name. Should be used
* instead of basic <code>Class.forName(className);</code> as it can
* try using contextual class loader, or use platform-specific workarounds
* (like on Android, GAE).
*/
public Class<?> findClass(String className) throws ClassNotFoundException
{
// By default, delegate to ClassUtil: can be overridden with custom handling
return ClassUtil.findClass(className);
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
}
/*
/**********************************************************
/* Public API, helper object recycling
/**********************************************************
*/
/**
* Method that can be used to get access to a reusable ObjectBuffer,
* useful for efficiently constructing Object arrays and Lists.
* Note that leased buffers should be returned once deserializer
* is done, to allow for reuse during same round of deserialization.
*/
public final ObjectBuffer leaseObjectBuffer()
{
ObjectBuffer buf = _objectBuffer;
if (buf == null) {
buf = new ObjectBuffer();
} else {
_objectBuffer = null;
}
return buf;
}
/**
* Method to call to return object buffer previously leased with
* {@link #leaseObjectBuffer}.
*
* @param buf Returned object buffer
*/
public final void returnObjectBuffer(ObjectBuffer buf)
{
/* Already have a reusable buffer? Let's retain bigger one
* (or if equal, favor newer one, shorter life-cycle)
*/
if (_objectBuffer == null
|| buf.initialCapacity() >= _objectBuffer.initialCapacity()) {
_objectBuffer = buf;
}
}
/**
* Method for accessing object useful for building arrays of
* primitive types (such as int[]).
*/
public final ArrayBuilders getArrayBuilders()
{
if (_arrayBuilders == null) {
_arrayBuilders = new ArrayBuilders();
}
return _arrayBuilders;
}
/*
/**********************************************************
/* Extended API: handler instantiation
/**********************************************************
*/
public abstract JsonDeserializer<Object> deserializerInstance(Annotated annotated,
Object deserDef)
throws JsonMappingException;
public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
Object deserDef)
throws JsonMappingException;
/*
/**********************************************************
/* Extended API: resolving contextual deserializers; called
/* by structured deserializers for their value/component
/* deserializers
/**********************************************************
*/
/**
* Method called for primary property deserializers (ones
* directly created to deserialize values of a POJO property),
* to handle details of resolving
* {@link ContextualDeserializer} with given property context.
*
* @param prop Property for which the given primary deserializer is used; never null.
*
* @since 2.3
*/
public JsonDeserializer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS><?> handlePrimaryContextualization(JsonDeserializer<?> deser,
BeanProperty prop)
throws JsonMappingException
{
if (deser != null) {
if (deser instanceof ContextualDeserializer) {
deser = ((ContextualDeserializer) deser).createContextual(this, prop);
}
}
return deser;
}
/**
* Method called for secondary property deserializers (ones
* NOT directly created to deal with an annotatable POJO property,
* but instead created as a component -- such as value deserializers
* for structured types, or deserializers for root values)
* to handle details of resolving
* {@link ContextualDeserializer} with given property context.
* Given that these deserializers are not directly related to given property
* (or, in case of root value property, to any property), annotations
* accessible may or may not be relevant.
*
* @param prop Property for which deserializer is used, if any; null
* when deserializing root values
*
* @since 2.3
*/
public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser,
BeanProperty prop)
throws JsonMappingException {
if (deser != null && (deser instanceof ContextualDeserializer)) {
deser = ((ContextualDeserializer) deser).createContextual(this, prop);
}
return deser;
}
/*
/**********************************************************
/* Parsing methods that may use reusable/-cyclable objects
/**********************************************************
*/
/**
* Convenience method for parsing a Date from given String, using
* currently configured date format (accessed using
* {@link DeserializationConfig#getDateFormat()}).
*<p>
* Implementation will handle thread-safety issues related to
* date formats such that first time this method is called,
* date format is cloned, and cloned instance will be retained
* for use during this deserialization round.
*/
public Date parseDate(String dateStr) throws IllegalArgumentException
{
try {
DateFormat df = getDateFormat();
return df.parse(dateStr);
} catch (ParseException e) {
throw new IllegalArgumentException("Failed to parse Date value '"+dateStr+"': "+e.getMessage());
}
}
/**
* Convenience method for constructing Calendar instance set
* to specified time, to be modified and used by caller.
*/
public
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>deserialize(p, this);
}
/*
/**********************************************************
/* Methods for problem handling, reporting
/**********************************************************
*/
/**
* Method deserializers can call to inform configured {@link DeserializationProblemHandler}s
* of an unrecognized property.
*
* @return True if there was a configured problem handler that was able to handle the
* problem
*/
/**
* Method deserializers can call to inform configured {@link DeserializationProblemHandler}s
* of an unrecognized property.
*/
public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
Object instanceOrClass, String propName)
throws IOException, JsonProcessingException
{
LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
if (h != null) {
while (h != null) {
// Can bail out if it's handled
if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
return true;
}
h = h.next();
}
}
return false;
}
/**
* Helper method for reporting a problem with unhandled unknown exception
*
* @param instanceOrClass Either value being populated (if one has been
* instantiated), or Class that indicates type that would be (or
* have been) instantiated
* @param deser Deserializer that had the problem, if called by deserializer
* (or on behalf of one)
*/
public void reportUnknownProperty(Object instanceOrClass, String fieldName,
JsonDeserializer<?> deser)
throws JsonMappingException
{
if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
return;
}
// Do we know properties that are expected instead?
Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
throw UnrecognizedPropertyException.from(_parser,
instanceOrClass, fieldName, propIds);
}
/*
/**********************************************************
/* Methods for constructing exceptions
/**********************************************************
*/
/**
* Helper method for constructing generic mapping exception for specified type
*/
public JsonMappingException mappingException(Class<?> targetClass) {
return mappingException(targetClass, _parser.getCurrentToken());
}
public JsonMappingException mappingException(Class<?> targetClass, JsonToken token)
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> {
return JsonMappingException.from(_parser, "Can not deserialize instance of "+_calcName(targetClass)+" out of "+token+" token");
}
/**
* Helper method for constructing generic mapping exception with specified
* message and current location information
*/
public JsonMappingException mappingException(String message) {
return JsonMappingException.from(getParser(), message);
}
/**
* Helper method for constructing instantiation exception for specified type,
* to indicate problem with physically constructing instance of
* specified class (missing constructor, exception from constructor)
*/
public JsonMappingException instantiationException(Class<?> instClass, Throwable t) {
return JsonMappingException.from(_parser,
"Can not construct instance of "+instClass.getName()+", problem: "+t.getMessage(), t);
}
public JsonMappingException instantiationException(Class<?> instClass, String msg) {
return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+", problem: "+msg);
}
/**
* Method that will construct an exception suitable for throwing when
* some String values are acceptable, but the one encountered is not.
*
*
* @deprecated Since 2.1 should use variant that takes value
*/
@Deprecated
public JsonMappingException weirdStringException(Class<?> instClass, String msg) {
return weirdStringException(null, instClass, msg);
}
/**
* Method that will construct an exception suitable for throwing when
* some String values are acceptable, but the one encountered is not.
*
* @param value String value from input being deserialized
* @param instClass Type that String should be deserialized into
* @param msg Message that describes specific problem
*
* @since 2.1
*/
public JsonMappingException weirdStringException(String value, Class<?> instClass, String msg) {
return InvalidFormatException.from(_parser,
"Can not construct instance of "+instClass.getName()+" from String value '"+_valueDesc()+"': "+msg,
value, instClass);
}
/**
* Helper method for constructing exception to indicate that input JSON
* Number was not suitable for deserializing into given type.
*/
@Deprecated
public JsonMappingException weirdNumberException(Class<?> instClass, String msg) {
return weirdStringException(null, instClass,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> msg);
}
/**
* Helper method for constructing exception to indicate that input JSON
* Number was not suitable for deserializing into given target type.
*/
public JsonMappingException weirdNumberException(Number value, Class<?> instClass, String msg) {
return InvalidFormatException.from(_parser,
"Can not construct instance of "+instClass.getName()+" from number value ("+_valueDesc()+"): "+msg,
null, instClass);
}
/**
* Helper method for constructing exception to indicate that given JSON
* Object field name was not in format to be able to deserialize specified
* key type.
*/
public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg) {
return InvalidFormatException.from(_parser,
"Can not construct Map key of type "+keyClass.getName()+" from String \""+_desc(keyValue)+"\": "+msg,
keyValue, keyClass);
}
/**
* Helper method for indicating that the current token was expected to be another
* token.
*/
public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken, String msg0) {
String msg = "Unexpected token ("+p.getCurrentToken()+"), expected "+expToken;
if (msg0 != null) {
msg = msg + ": "+msg0;
}
return JsonMappingException.from(p, msg);
}
/**
* Helper method for constructing exception to indicate that given
* type id (parsed from JSON) could not be converted to a Java type.
*/
public JsonMappingException unknownTypeException(JavaType type, String id) {
return JsonMappingException.from(_parser, "Could not resolve type id '"+id+"' into a subtype of "+type);
}
public JsonMappingException endOfInputException(Class<?> instClass) {
return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to deserialize a "
+instClass.getName());
}
/*
/**********************************************************
/* Overridable internal methods
/**********************************************************
*/
protected DateFormat getDateFormat()
{
if (_dateFormat != null) {
return _dateFormat;
}
/* 24-Feb-2012, tatu: At this point, all timezone configuration
* should have occured, with respect to
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> default dateformat
* and timezone configuration. But we still better clone
* an instance as formatters may be stateful.
*/
DateFormat df = _config.getDateFormat();
_dateFormat = df = (DateFormat) df.clone();
return df;
}
protected String determineClassName(Object instance) {
return ClassUtil.getClassDescription(instance);
}
/*
/**********************************************************
/* Other internal methods
/**********************************************************
*/
protected String _calcName(Class<?> cls) {
if (cls.isArray()) {
return _calcName(cls.getComponentType())+"[]";
}
return cls.getName();
}
protected String _valueDesc() {
try {
return _desc(_parser.getText());
} catch (Exception e) {
return "[N/A]";
}
}
protected String _desc(String desc) {
// !!! should we quote it? (in case there are control chars, linefeeds)
if (desc.length() > MAX_ERROR_STR_LEN) {
desc = desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN);
}
return desc;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
/**
* Abstract class that defines API used by {@link SerializerProvider}
* to obtain actual
* {@link JsonSerializer} instances from multiple distinct factories.
*/
public abstract class SerializerFactory
{
/*
/**********************************************************
/* Additional configuration methods
/**********************************************************
*/
/**
* Convenience method for creating a new factory instance with additional serializer
* provider; equivalent to calling
*<pre>
* withConfig(getConfig().withAdditionalSerializers(additional));
*<pre>
*/
public abstract SerializerFactory withAdditionalSerializers(Serializers additional);
public abstract SerializerFactory withAdditionalKeySerializers(Serializers additional);
/**
* Convenience method for creating a new factory instance with additional bean
* serializer modifier; equivalent to calling
*<pre>
* withConfig(getConfig().withSerializerModifier(modifier));
*<pre>
*/
public abstract SerializerFactory withSerializerModifier(BeanSerializerModifier modifier);
/*
/**********************************************************
/* Basic SerializerFactory API:
/**********************************************************
*/
/**
* Method called to create (or, for immutable serializers, reuse) a serializer for given type.
*
* @param prov Provider that needs to be used to resolve annotation-provided
* serializers (but NOT for others)
*
* @since 2.1 (earlier versions had method with different signature)
*/
public abstract JsonSerializer<Object> createSerializer(SerializerProvider prov,
JavaType baseType)
throws JsonMappingException;
/**
* Method called to create a type information serializer for given base type,
* if one is needed. If not needed (no polymorphic handling configured), should
* return null.
*
* @param baseType Declared type to use as the base type for type information serializer
*
* @return Type serializer to use for the base type, if one is needed; null if not.
*/
public abstract TypeSerializer createTypeSerializer(SerializationConfig config,
JavaType baseType)
throws JsonMappingException;
/**
* Method called to create serializer to use for serializing JSON property names (which must
* be output as <code>JsonToken.FIELD_NAME</code>) for Map
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> that has specified declared
* key type, and is for specified property (or, if property is null, as root value)
*
* @param baseType Declared type for Map keys
* @param defaultImpl Default key serializer implementation to use, if no custom ones
* are found (may be null)
*
* @return Serializer to use, if factory knows it; null if not (in which case default
* serializer is to be used)
*/
public abstract JsonSerializer<Object> createKeySerializer(SerializationConfig config,
JavaType baseType, JsonSerializer<Object> defaultImpl)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> Enum<T>>" etc)
bindings._addPlaceholder(name);
// About only useful piece of information is the lower bound (which is at least Object.class)
Type lowerBound = var.getBounds()[0];
JavaType type = (lowerBound == null) ? TypeFactory.unknownType()
: bindings.resolveType(lowerBound);
bindings.addBinding(var.getName(), type);
}
}
return bindings.resolveType(getGenericType());
}
/*
/**********************************************************
/* Partial Annotated impl
/**********************************************************
*/
@Override
public final <A extends Annotation> A getAnnotation(Class<A> acls) {
return _annotations.get(acls);
}
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
public final AnnotationMap getParameterAnnotations(int index)
{
if (_paramAnnotations != null) {
if (index >= 0 && index <= _paramAnnotations.length) {
return _paramAnnotations[index];
}
}
return null;
}
public final AnnotatedParameter getParameter(int index) {
return new AnnotatedParameter(this, getGenericParameterType(index),
getParameterAnnotations(index), index);
}
public abstract int getParameterCount();
public abstract Class<?> getRawParameterType(int index);
public abstract Type getGenericParameterType(int index);
/**
* Method called to fully resolve type of one of parameters, given
* specified type variable bindings.
*/
public final JavaType resolveParameterType(int index, TypeBindings bindings) {
return bindings.resolveType(getGenericParameterType(index));
}
public final int getAnnotationCount() { return _annotations.size(); }
/**
* Method that can be used to (try to) call this object without arguments.
* This may succeed or fail, depending on expected number
* of arguments: caller needs to take care to pass correct number.
* Exceptions are thrown directly from actual low-level call.
*<p>
* Note: only works for constructors and static methods.
*/
public abstract Object call() throws Exception;
/**
* Method that can be used to (try to) call this object with specified arguments.
* This may succeed or fail, depending on expected number
* of arguments: caller needs to take care to pass correct number.
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
* Exceptions are thrown directly from actual low-level call.
*<p>
* Note: only works for constructors and static methods.
*/
public abstract Object call(Object[] args) throws Exception;
/**
* Method that can be used to (try to) call this object with single arguments.
* This may succeed or fail, depending on expected number
* of arguments: caller needs to take care to pass correct number.
* Exceptions are thrown directly from actual low-level call.
*<p>
* Note: only works for constructors and static methods.
*/
public abstract Object call1(Object arg) throws Exception;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> serializer definitions");
}
return new BeanSerializerFactory(config);
}
@Override
protected Iterable<Serializers> customSerializers() {
return _factoryConfig.serializers();
}
/*
/**********************************************************
/* SerializerFactory impl
/**********************************************************
*/
/**
* Main serializer constructor method. We will have to be careful
* with respect to ordering of various method calls: essentially
* we want to reliably figure out which classes are standard types,
* and which are beans. The problem is that some bean Classes may
* implement standard interfaces (say, {@link java.lang.Iterable}.
*<p>
* Note: sub-classes may choose to complete replace implementation,
* if they want to alter priority of serializer lookups.
*/
@Override
@SuppressWarnings("unchecked")
public JsonSerializer<Object> createSerializer(SerializerProvider prov,
JavaType origType)
throws JsonMappingException
{
// Very first thing, let's check if there is explicit serializer annotation:
final SerializationConfig config = prov.getConfig();
BeanDescription beanDesc = config.introspect(origType);
JsonSerializer<?> ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
if (ser != null) {
return (JsonSerializer<Object>) ser;
}
boolean staticTyping;
// Next: we may have annotations that further define types to use...
JavaType type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), origType);
if (type == origType) { // no changes, won't force static typing
staticTyping = false;
} else { // changes; assume static typing; plus, need to re-introspect if class differs
staticTyping = true;
if (!type.hasRawClass(origType.getRawClass())) {
beanDesc = config.introspect(type);
}
}
// Slight detour: do we have a Converter to consider?
Converter<Object,Object> conv = beanDesc.findSerializationConverter();
if (conv == null) { // no, simple
return (JsonSerializer<Object>) _createSerializer2(prov, type, beanDesc, staticTyping);
}
JavaType delegateType = conv.getOutputType(prov.getTypeFactory());
// One more twist, as per [Issue#288]; probably need to get new Bean
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Desc
if (!delegateType.hasRawClass(type.getRawClass())) {
beanDesc = config.introspect(delegateType);
// [#359]: explicitly check (again) for @JsonSerializer...
ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
}
if (ser == null) {
ser = _createSerializer2(prov, delegateType, beanDesc, true);
}
return new StdDelegatingSerializer(conv, delegateType, ser);
}
protected JsonSerializer<?> _createSerializer2(SerializerProvider prov,
JavaType type, BeanDescription beanDesc, boolean staticTyping)
throws JsonMappingException
{
// Then JsonSerializable, @JsonValue etc:
JsonSerializer<?> ser = findSerializerByAnnotations(prov, type, beanDesc);
if (ser != null) {
return ser;
}
final SerializationConfig config = prov.getConfig();
// Container types differ from non-container types
// (note: called method checks for module-provided serializers)
if (type.isContainerType()) {
if (!staticTyping) {
staticTyping = usesStaticTyping(config, beanDesc, null);
// [Issue#23]: Need to figure out how to force passed parameterization
// to stick...
/*
if (property == null) {
JavaType t = origType.getContentType();
if (t != null && !t.hasRawClass(Object.class)) {
staticTyping = true;
}
}
*/
}
// 03-Aug-2012, tatu: As per [Issue#40], may require POJO serializer...
ser = buildContainerSerializer(prov, type, beanDesc, staticTyping);
// Will return right away, since called method does post-processing:
if (ser != null) {
return ser;
}
} else {
// Modules may provide serializers of POJO types:
for (Serializers serializers : customSerializers()) {
ser = serializers.findSerializer(config, type, beanDesc);
if (ser != null) {
break;
}
}
}
// Otherwise, we will check "primary types"; both marker types that
// indicate specific handling (JsonSerializable), or main types that have
// precedence over container types
if (ser == null) {
ser =
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> findSerializerByLookup(type, config, beanDesc, staticTyping);
if (ser == null) {
ser = findSerializerByPrimaryType(prov, type, beanDesc, staticTyping);
if (ser == null) {
// And this is where this class comes in: if type is not a
// known "primary JDK type", perhaps it's a bean? We can still
// get a null, if we can't find a single suitable bean property.
ser = findBeanSerializer(prov, type, beanDesc);
// Finally: maybe we can still deal with it as an implementation of some basic JDK interface?
if (ser == null) {
ser = findSerializerByAddonType(config, type, beanDesc, staticTyping);
}
}
}
}
if (ser != null) {
// [Issue#120]: Allow post-processing
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
ser = mod.modifySerializer(config, beanDesc, ser);
}
}
}
return ser;
}
/*
/**********************************************************
/* Other public methods that are not part of
/* JsonSerializerFactory API
/**********************************************************
*/
/**
* Method that will try to construct a {@link BeanSerializer} for
* given class. Returns null if no properties are found.
*/
public JsonSerializer<Object> findBeanSerializer(SerializerProvider prov, JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
// First things first: we know some types are not beans...
if (!isPotentialBeanType(type.getRawClass())) {
// 03-Aug-2012, tatu: Except we do need to allow serializers for Enums,
// as per [Issue#24]
if (!type.isEnumType()) {
return null;
}
}
return constructBeanSerializer(prov, beanDesc);
}
/**
* Method called to create a type information serializer for values of given
* non-container property
* if one is needed. If not needed (no polymorphic handling configured), should
* return null.
*
* @param baseType Declared type to use as the base type for type information serializer
*
* @return Type serializer to use for property values
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, if one is needed; null if not.
*/
public TypeSerializer findPropertyTypeSerializer(JavaType baseType,
SerializationConfig config, AnnotatedMember accessor)
throws JsonMappingException
{
AnnotationIntrospector ai = config.getAnnotationIntrospector();
TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(config, accessor, baseType);
// Defaulting: if no annotations on member, check value class
if (b == null) {
return createTypeSerializer(config, baseType);
}
Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(
accessor, config, ai, baseType);
return b.buildTypeSerializer(config, baseType, subtypes);
}
/**
* Method called to create a type information serializer for values of given
* container property
* if one is needed. If not needed (no polymorphic handling configured), should
* return null.
*
* @param containerType Declared type of the container to use as the base type for type information serializer
*
* @return Type serializer to use for property value contents, if one is needed; null if not.
*/
public TypeSerializer findPropertyContentTypeSerializer(JavaType containerType,
SerializationConfig config, AnnotatedMember accessor)
throws JsonMappingException
{
JavaType contentType = containerType.getContentType();
AnnotationIntrospector ai = config.getAnnotationIntrospector();
TypeResolverBuilder<?> b = ai.findPropertyContentTypeResolver(config, accessor, containerType);
// Defaulting: if no annotations on member, check value class
if (b == null) {
return createTypeSerializer(config, contentType);
}
Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(accessor,
config, ai, contentType);
return b.buildTypeSerializer(config, contentType, subtypes);
}
/*
/**********************************************************
/* Overridable non-public factory methods
/**********************************************************
*/
/**
* Method called to construct serializer for serializing specified bean type.
*
* @since 2.1
*/
@SuppressWarnings("unchecked")
protected JsonSerializer<Object> constructBeanSerializer(SerializerProvider prov,
BeanDescription beanDesc)
throws JsonMappingException
{
// 13-Oct-2010, tatu
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>PING);
JavaType valueType = type.getContentType();
TypeSerializer typeSer = createTypeSerializer(config, valueType);
// last 2 nulls; don't know key, value serializers (yet)
// TODO: support '@JsonIgnoreProperties' with any setter?
MapSerializer mapSer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
typeSer, null, null, /*filterId*/ null);
// TODO: can we find full PropertyName?
PropertyName name = new PropertyName(anyGetter.getName());
BeanProperty.Std anyProp = new BeanProperty.Std(name, valueType, null,
beanDesc.getClassAnnotations(), anyGetter, PropertyMetadata.STD_OPTIONAL);
builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, mapSer));
}
// Next: need to gather view information, if any:
processViews(config, builder);
// Finally: let interested parties mess with the result bit more...
if (_factoryConfig.hasSerializerModifiers()) {
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
builder = mod.updateBuilder(config, beanDesc, builder);
}
}
JsonSerializer<Object> ser = (JsonSerializer<Object>) builder.build();
/* However, after all modifications: no properties, no serializer
* (note; as per [JACKSON-670], check was moved later on from an earlier location)
*/
if (ser == null) {
/* 27-Nov-2009, tatu: Except that as per [JACKSON-201], we are
* ok with that as long as it has a recognized class annotation
* (which may come from a mix-in too)
*/
if (beanDesc.hasKnownClassAnnotations()) {
return builder.createDummy();
}
}
return ser;
}
protected ObjectIdWriter constructObjectIdHandler(SerializerProvider prov,
BeanDescription beanDesc, List<BeanPropertyWriter> props)
throws JsonMappingException
{
ObjectIdInfo objectIdInfo = beanDesc.getObjectIdInfo();
if (objectIdInfo == null) {
return null;
}
ObjectIdGenerator<?> gen;
Class<?> implClass = objectIdInfo.getGeneratorType();
// Just one special case: Property-
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>);
}
protected BeanSerializerBuilder constructBeanSerializerBuilder(BeanDescription beanDesc) {
return new BeanSerializerBuilder(beanDesc);
}
/*
/**********************************************************
/* Overridable non-public introspection methods
/**********************************************************
*/
/**
* Helper method used to skip processing for types that we know
* can not be (i.e. are never consider to be) beans:
* things like primitives, Arrays, Enums, and proxy types.
*<p>
* Note that usually we shouldn't really be getting these sort of
* types anyway; but better safe than sorry.
*/
protected boolean isPotentialBeanType(Class<?> type)
{
return (ClassUtil.canBeABeanType(type) == null) && !ClassUtil.isProxyType(type);
}
/**
* Method used to collect all actual serializable properties.
* Can be overridden to implement custom detection schemes.
*/
protected List<BeanPropertyWriter> findBeanProperties(SerializerProvider prov,
BeanDescription beanDesc, BeanSerializerBuilder builder)
throws JsonMappingException
{
List<BeanPropertyDefinition> properties = beanDesc.findProperties();
final SerializationConfig config = prov.getConfig();
// [JACKSON-429]: ignore specified types
removeIgnorableTypes(config, beanDesc, properties);
// and possibly remove ones without matching mutator...
if (config.isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)) {
removeSetterlessGetters(config, beanDesc, properties);
}
// nothing? can't proceed (caller may or may not throw an exception)
if (properties.isEmpty()) {
return null;
}
// null is for value type serializer, which we don't have access to from here (ditto for bean prop)
boolean staticTyping = usesStaticTyping(config, beanDesc, null);
PropertyBuilder pb = constructPropertyBuilder(config, beanDesc);
ArrayList<BeanPropertyWriter> result = new ArrayList<BeanPropertyWriter>(properties.size());
TypeBindings typeBind = beanDesc.bindingsForBeanType();
for (BeanPropertyDefinition property : properties) {
final AnnotatedMember accessor = property.getAccessor();
// [JACKSON-762]: type id? Requires special handling:
if (property.is
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>-ignorable
if (result == null) {
result = Boolean.FALSE;
}
ignores.put(type, result);
}
// lotsa work, and yes, it is ignorable type, so:
if (result.booleanValue()) {
it.remove();
}
}
}
/**
* Helper method that will remove all properties that do not have a mutator.
*/
protected void removeSetterlessGetters(SerializationConfig config, BeanDescription beanDesc,
List<BeanPropertyDefinition> properties)
{
Iterator<BeanPropertyDefinition> it = properties.iterator();
while (it.hasNext()) {
BeanPropertyDefinition property = it.next();
// one caveat: as per [JACKSON-806], only remove implicit properties;
// explicitly annotated ones should remain
if (!property.couldDeserialize() && !property.isExplicitlyIncluded()) {
it.remove();
}
}
}
/*
/**********************************************************
/* Internal helper methods
/**********************************************************
*/
/**
* Secondary helper method for constructing {@link BeanPropertyWriter} for
* given member (field or method).
*/
protected BeanPropertyWriter _constructWriter(SerializerProvider prov,
BeanPropertyDefinition propDef, TypeBindings typeContext,
PropertyBuilder pb, boolean staticTyping, AnnotatedMember accessor)
throws JsonMappingException
{
final PropertyName name = propDef.getFullName();
if (prov.canOverrideAccessModifiers()) {
accessor.fixAccess();
}
JavaType type = accessor.getType(typeContext);
BeanProperty.Std property = new BeanProperty.Std(name, type, propDef.getWrapperName(),
pb.getClassAnnotations(), accessor, propDef.getMetadata());
// Does member specify a serializer? If so, let's use it.
JsonSerializer<?> annotatedSerializer = findSerializerFromAnnotation(prov,
accessor);
/* 02-Feb-2012, tatu: Unlike most other code paths, serializer produced
* here will NOT be resolved or contextualized, unless done here, so:
*/
if (annotatedSerializer instanceof ResolvableSerializer) {
((ResolvableSerializer) annotatedSerializer).resolve(prov);
}
// 05-Sep-2013, tatu: should be primary property serializer so:
annotatedSerializer = prov
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> sers.put(Void.class, NullSerializer.instance);
sers.put(Void.TYPE, NullSerializer.instance);
return sers.entrySet();
}
/*
/**********************************************************
/* Serializers for atomic types
/**********************************************************
*/
public final static class AtomicBooleanSerializer
extends StdScalarSerializer<AtomicBoolean>
{
public AtomicBooleanSerializer() { super(AtomicBoolean.class, false); }
@Override
public void serialize(AtomicBoolean value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
jgen.writeBoolean(value.get());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("boolean", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
visitor.expectBooleanFormat(typeHint);
}
}
public final static class AtomicIntegerSerializer
extends StdScalarSerializer<AtomicInteger>
{
public AtomicIntegerSerializer() { super(AtomicInteger.class, false); }
@Override
public void serialize(AtomicInteger value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
jgen.writeNumber(value.get());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("integer", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
if (v2 != null) {
v2.numberType(JsonParser.NumberType.INT);
}
}
}
public final static class AtomicLongSerializer
extends StdScalarSerializer<AtomicLong>
{
public AtomicLongSerializer() { super(AtomicLong.class, false); }
@Override
public void serialize(AtomicLong value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
jgen.writeNumber(value.get());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("integer", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> JavaType typeHint)
throws JsonMappingException
{
JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
if (v2 != null) {
v2.numberType(JsonParser.NumberType.LONG);
}
}
}
public final static class AtomicReferenceSerializer
extends StdSerializer<AtomicReference<?>>
{
public AtomicReferenceSerializer() { super(AtomicReference.class, false); }
@Override
public void serialize(AtomicReference<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
provider.defaultSerializeValue(value.get(), jgen);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("any", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectAnyFormat(typeHint);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
if (m != null) {
AnnotatedMethod am = _constructMethod(m);
_addMixOvers(mixIn.getAnnotated(), am, false);
_memberMethods.add(am);
}
} catch (Exception e) { }
}
}
}
}
/**
* Method that will collect all member (non-static) fields
* that are either public, or have at least a single annotation
* associated with them.
*/
private void resolveFields()
{
Map<String,AnnotatedField> foundFields = _findFields(_class, null);
if (foundFields == null || foundFields.size() == 0) {
_fields = Collections.emptyList();
} else {
_fields = new ArrayList<AnnotatedField>(foundFields.size());
_fields.addAll(foundFields.values());
}
}
/*
/**********************************************************
/* Helper methods for resolving class annotations
/* (resolution consisting of inheritance, overrides,
/* and injection of mix-ins as necessary)
/**********************************************************
*/
/**
* Helper method for adding any mix-in annotations specified
* class might have.
*/
protected void _addClassMixIns(AnnotationMap annotations, Class<?> toMask)
{
if (_mixInResolver != null) {
_addClassMixIns(annotations, toMask, _mixInResolver.findMixInClassFor(toMask));
}
}
protected void _addClassMixIns(AnnotationMap annotations, Class<?> toMask,
Class<?> mixin)
{
if (mixin == null) {
return;
}
// Ok, first: annotations from mix-in class itself:
_addAnnotationsIfNotPresent(annotations, mixin.getDeclaredAnnotations());
/* And then from its supertypes, if any. But note that we will
* only consider super-types up until reaching the masked
* class (if found); this because often mix-in class
* is a sub-class (for convenience reasons). And if so, we
* absolutely must NOT include super types of masked class,
* as that would inverse precedence of annotations.
*/
for (Class<?> parent : ClassUtil.findSuperTypes(mixin, toMask)) {
_addAnnotationsIfNotPresent(annotations, parent.getDeclaredAnnotations());
}
}
/*
/**********************************************************
/* Helper
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(_delegate.withIgnorableProperties(ignorableProps),
_orderedProperties);
}
@Override
protected BeanDeserializerBase asArrayDeserializer() {
return this;
}
/*
/**********************************************************
/* JsonDeserializer implementation
/**********************************************************
*/
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Let's delegate just in case we got a JSON Object (could error out, alternatively?)
if (jp.getCurrentToken() != JsonToken.START_ARRAY) {
return _deserializeFromNonArray(jp, ctxt);
}
if (!_vanillaProcessing) {
return _deserializeNonVanilla(jp, ctxt);
}
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
final SettableBeanProperty[] props = _orderedProperties;
int i = 0;
final int propCount = props.length;
while (true) {
if (jp.nextToken() == JsonToken.END_ARRAY) {
return bean;
}
if (i == propCount) {
break;
}
SettableBeanProperty prop = props[i];
if (prop != null) { // normal case
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, prop.getName(), ctxt);
}
} else { // just skip?
jp.skipChildren();
}
++i;
}
// Ok; extra fields? Let's fail, unless ignoring extra props is fine
if (!_ignoreAllUnknown) {
throw ctxt.mappingException("Unexpected JSON values; expected at most "+propCount+" properties (in JSON Array)");
}
// otherwise, skip until end
while (jp.nextToken() != JsonToken.END_ARRAY) {
jp.skipChildren();
}
return bean;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
/* No good way to verify that we have an array... although could I guess
* check via JsonParser. So let's assume everything is working fine, for now.
*/
if (_injectables != null) {
injectValues(ctxt, bean);
}
final SettableBeanProperty[] props
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> = _orderedProperties;
int i = 0;
final int propCount = props.length;
while (true) {
if (jp.nextToken() == JsonToken.END_ARRAY) {
return bean;
}
if (i == propCount) {
break;
}
SettableBeanProperty prop = props[i];
if (prop != null) { // normal case
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, prop.getName(), ctxt);
}
} else { // just skip?
jp.skipChildren();
}
++i;
}
// Ok; extra fields? Let's fail, unless ignoring extra props is fine
if (!_ignoreAllUnknown) {
throw ctxt.mappingException("Unexpected JSON values; expected at most "+propCount+" properties (in JSON Array)");
}
// otherwise, skip until end
while (jp.nextToken() != JsonToken.END_ARRAY) {
jp.skipChildren();
}
return bean;
}
// needed since 2.1
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
return _deserializeFromNonArray(jp, ctxt);
}
/*
/**********************************************************
/* Helper methods, non-standard creation
/**********************************************************
*/
/**
* Alternate deserialization method that has to check many more configuration
* aspects than the "vanilla" processing.
*/
protected Object _deserializeNonVanilla(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_nonStandardCreation) {
return _deserializeWithCreator(jp, ctxt);
}
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (_injectables != null) {
injectValues(ctxt, bean);
}
Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
final SettableBeanProperty[] props = _orderedProperties;
int i = 0;
final int propCount = props.length;
while (true) {
if (jp.nextToken() == JsonToken.END_ARRAY) {
return bean;
}
if (i == propCount) {
break
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>;
}
SettableBeanProperty prop = props[i];
++i;
if (prop != null) { // normal case
if (activeView == null || prop.visibleInView(activeView)) {
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, prop.getName(), ctxt);
}
continue;
}
}
// otherwise, skip it (view-filtered, no prop etc)
jp.skipChildren();
}
// Ok; extra fields? Let's fail, unless ignoring extra props is fine
if (!_ignoreAllUnknown) {
throw ctxt.mappingException("Unexpected JSON values; expected at most "+propCount+" properties (in JSON Array)");
}
// otherwise, skip until end
while (jp.nextToken() != JsonToken.END_ARRAY) {
jp.skipChildren();
}
return bean;
}
protected Object _deserializeWithCreator(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
}
if (_propertyBasedCreator != null) {
return _deserializeUsingPropertyBased(jp, ctxt);
}
// should only occur for abstract types...
if (_beanType.isAbstract()) {
throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_beanType
+" (need to add/enable type information?)");
}
throw JsonMappingException.from(jp, "No suitable constructor found for type "
+_beanType+": can not instantiate from JSON object (need to add/enable type information?)");
}
/**
* Method called to deserialize bean using "property-based creator":
* this means that a non-default constructor or factory method is
* called, and then possibly other setters. The trick is that
* values for creator method need to be buffered, first; and
* due to non-guaranteed ordering possibly some other properties
* as well.
*/
@Override
protected final Object _deserializeUsingPropertyBased(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
final SettableBeanProperty[] props = _orderedProperties;
final int propCount = props.length;
int i = 0;
Object bean = null;
for (; jp.nextToken() != JsonToken.END_ARRAY; ++i) {
SettableBeanProperty prop = (i < propCount) ? props[i] : null;
if (prop == null) { // we get null if there are extra elements; maybe otherwise too?
jp.skipChildren();
continue;
}
// if we have already constructed POJO, things are simple:
if (bean != null) {
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, prop.getName(), ctxt);
}
continue;
}
final String propName = prop.getName();
// if not yet, maybe we got a creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
/* 23-Jul-2012, tatu: Not sure if these could ever be properly
* supported (since ordering of elements may not be guaranteed);
* but make explicitly non-supported for now.
*/
throw ctxt.mappingException("Can not support implicit polymorphic deserialization for POJOs-as-Arrays style: "
+"nominal type "+_beanType.getRawClass().getName()+", actual type "+bean.getClass().getName());
}
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
buffer.bufferProperty(prop, prop.
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>deserialize(jp, ctxt));
}
// In case we didn't quite get all the creator properties, we may have to do this:
if (bean == null) {
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
}
return bean;
}
/*
/**********************************************************
/* Helper methods, error reporting
/**********************************************************
*/
protected Object _deserializeFromNonArray(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Let's start with failure
throw ctxt.mappingException("Can not deserialize a POJO (of type "+_beanType.getRawClass().getName()
+") from non-Array representation (token: "+jp.getCurrentToken()
+"): type/property designed to be serialized as JSON Array");
// in future, may allow use of "standard" POJO serialization as well; if so, do:
//return _delegate.deserialize(jp, ctxt);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DateFormat;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* Compared to regular {@link java.util.Date} serialization, we do use String
* representation here. Why? Basically to truncate of time part, since
* that should not be used by plain SQL date.
*/
@JacksonStdImpl
public class SqlDateSerializer
extends DateTimeSerializerBase<java.sql.Date>
{
public SqlDateSerializer() {
/* 12-Apr-2014, tatu: for now, pass explicit 'false' to mean 'not using timestamp',
* for backwards compatibility; this differs from other Date/Calendar types.
*/
this(Boolean.FALSE);
}
protected SqlDateSerializer(Boolean useTimestamp) {
super(java.sql.Date.class, useTimestamp, null);
}
@Override
public SqlDateSerializer withFormat(Boolean timestamp, DateFormat customFormat) {
return new SqlDateSerializer(timestamp);
}
@Override
protected long _timestamp(java.sql.Date value) {
return (value == null) ? 0L : value.getTime();
}
@Override
public void serialize(java.sql.Date value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
if (_useTimestamp) {
jgen.writeNumber(_timestamp(value));
} else {
jgen.writeString(value.toString());
}
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
//todo: (ryan) add a format for the date in the schema?
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
{
_acceptJsonFormatVisitor(visitor, type
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* Also: default bean access will not do much good with Class.class. But
* we can just serialize the class name and that should be enough.
*/
public class ClassSerializer
extends StdScalarSerializer<Class<?>>
{
public ClassSerializer() { super(Class.class, false); }
@Override
public void serialize(Class<?> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
jgen.writeString(value.getName());
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectStringFormat(typeHint);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, null);
}
protected StdKeyDeserializer(int kind, Class<?> cls, FromStringDeserializer<?> deser) {
_kind = kind;
_keyClass = cls;
_deser = deser;
}
public static StdKeyDeserializer forType(Class<?> raw)
{
int kind;
// first common types:
if (raw == String.class || raw == Object.class) {
return StringKD.forType(raw);
} else if (raw == UUID.class) {
kind = TYPE_UUID;
} else if (raw == Integer.class) {
kind = TYPE_INT;
} else if (raw == Long.class) {
kind = TYPE_LONG;
} else if (raw == Date.class) {
kind = TYPE_DATE;
} else if (raw == Calendar.class) {
kind = TYPE_CALENDAR;
// then less common ones...
} else if (raw == Boolean.class) {
kind = TYPE_BOOLEAN;
} else if (raw == Byte.class) {
kind = TYPE_BYTE;
} else if (raw == Character.class) {
kind = TYPE_CHAR;
} else if (raw == Short.class) {
kind = TYPE_SHORT;
} else if (raw == Float.class) {
kind = TYPE_FLOAT;
} else if (raw == Double.class) {
kind = TYPE_DOUBLE;
} else if (raw == Locale.class) {
FromStringDeserializer<?> deser = FromStringDeserializer.findDeserializer(Locale.class);
return new StdKeyDeserializer(TYPE_LOCALE, raw, deser);
} else {
return null;
}
return new StdKeyDeserializer(kind, raw);
}
@Override
public Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (key == null) { // is this even legal call?
return null;
}
try {
Object result = _parse(key, ctxt);
if (result != null) {
return result;
}
} catch (Exception re) {
throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation: "+re.getMessage());
}
if (_keyClass.isEnum() && ctxt.getConfig().
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
return null;
}
throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation");
}
public Class<?> getKeyClass() { return _keyClass; }
protected Object _parse(String key, DeserializationContext ctxt) throws Exception
{
switch (_kind) {
case TYPE_BOOLEAN:
if ("true".equals(key)) {
return Boolean.TRUE;
}
if ("false".equals(key)) {
return Boolean.FALSE;
}
throw ctxt.weirdKeyException(_keyClass, key, "value not 'true' or 'false'");
case TYPE_BYTE:
{
int value = _parseInt(key);
// as per [JACKSON-804], allow range up to 255, inclusive
if (value < Byte.MIN_VALUE || value > 255) {
throw ctxt.weirdKeyException(_keyClass, key, "overflow, value can not be represented as 8-bit value");
}
return Byte.valueOf((byte) value);
}
case TYPE_SHORT:
{
int value = _parseInt(key);
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
throw ctxt.weirdKeyException(_keyClass, key, "overflow, value can not be represented as 16-bit value");
}
return Short.valueOf((short) value);
}
case TYPE_CHAR:
if (key.length() == 1) {
return Character.valueOf(key.charAt(0));
}
throw ctxt.weirdKeyException(_keyClass, key, "can only convert 1-character Strings");
case TYPE_INT:
return _parseInt(key);
case TYPE_LONG:
return _parseLong(key);
case TYPE_FLOAT:
/* 22-Jan-2009, tatu: Bounds/range checks would be tricky
* here, so let's not bother even trying...
*/
return Float.valueOf((float) _parseDouble(key));
case TYPE_DOUBLE:
return _parseDouble(key);
case TYPE_LOCALE:
try {
return _deser._deserialize(key, ctxt);
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> } catch (IOException e) {
throw ctxt.weirdKeyException(_keyClass, key, "unable to parse key as locale");
}
case TYPE_DATE:
return ctxt.parseDate(key);
case TYPE_CALENDAR:
java.util.Date date = ctxt.parseDate(key);
return (date == null) ? null : ctxt.constructCalendar(date);
case TYPE_UUID:
return UUID.fromString(key);
}
return null;
}
/*
/**********************************************************
/* Helper methods for sub-classes
/**********************************************************
*/
protected int _parseInt(String key) throws IllegalArgumentException {
return Integer.parseInt(key);
}
protected long _parseLong(String key) throws IllegalArgumentException {
return Long.parseLong(key);
}
protected double _parseDouble(String key) throws IllegalArgumentException {
return NumberInput.parseDouble(key);
}
/*
/**********************************************************
/* First: the standard "String as String" deserializer
/**********************************************************
*/
@JacksonStdImpl
final static class StringKD extends StdKeyDeserializer
{
private static final long serialVersionUID = 1L;
private final static StringKD sString = new StringKD(String.class);
private final static StringKD sObject = new StringKD(Object.class);
private StringKD(Class<?> nominalType) { super(-1, nominalType); }
public static StringKD forType(Class<?> nominalType)
{
if (nominalType == String.class) {
return sString;
}
if (nominalType == Object.class) {
return sObject;
}
return new StringKD(nominalType);
}
@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return key;
}
}
/*
/**********************************************************
/* Key deserializer implementations; other
/**********************************************************
*/
/**
* Key deserializer that wraps a "regular" deserializer (but one
* that must recognize FIELD_NAMEs as text!) to reuse existing
* handlers as key handlers.
*/
final static class DelegatingKD
extends KeyDeserializer // note: NOT the std one
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
final protected Class<?> _keyClass;
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> protected final JsonDeserializer<?> _delegate;
protected DelegatingKD(Class<?> cls, JsonDeserializer<?> deser) {
_keyClass = cls;
_delegate = deser;
}
@Override
public final Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (key == null) { // is this even legal call?
return null;
}
try {
// Ugh... should not have to give parser which may or may not be correct one...
Object result = _delegate.deserialize(ctxt.getParser(), ctxt);
if (result != null) {
return result;
}
} catch (Exception re) {
throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation: "+re.getMessage());
}
throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation");
}
public Class<?> getKeyClass() { return _keyClass; }
}
@JacksonStdImpl
final static class EnumKD extends StdKeyDeserializer
{
private static final long serialVersionUID = 1L;
protected final EnumResolver<?> _resolver;
protected final AnnotatedMethod _factory;
protected EnumKD(EnumResolver<?> er, AnnotatedMethod factory) {
super(-1, er.getEnumClass());
_resolver = er;
_factory = factory;
}
@Override
public Object _parse(String key, DeserializationContext ctxt) throws JsonMappingException
{
if (_factory != null) {
try {
return _factory.call1(key);
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e);
}
}
Enum<?> e = _resolver.findEnum(key);
if (e == null && !ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
throw ctxt.weirdKeyException(_keyClass, key, "not one of values for Enum class");
}
return e;
}
}
/**
* Key deserializer that calls a single-string-arg constructor
* to instantiate desired key type.
*/
final static class StringCtorKeyDeserializer extends StdKeyDeserializer
{
private static final long serialVersionUID = 1L;
protected final Constructor<?> _ctor;
public StringCtor
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>KeyDeserializer(Constructor<?> ctor) {
super(-1, ctor.getDeclaringClass());
_ctor = ctor;
}
@Override
public Object _parse(String key, DeserializationContext ctxt) throws Exception
{
return _ctor.newInstance(key);
}
}
/**
* Key deserializer that calls a static no-args factory method
* to instantiate desired key type.
*/
final static class StringFactoryKeyDeserializer extends StdKeyDeserializer
{
private static final long serialVersionUID = 1L;
final Method _factoryMethod;
public StringFactoryKeyDeserializer(Method fm) {
super(-1, fm.getDeclaringClass());
_factoryMethod = fm;
}
@Override
public Object _parse(String key, DeserializationContext ctxt) throws Exception
{
return _factoryMethod.invoke(null, key);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import com.fasterxml.jackson.core.*;
/**
* Checked exception used to signal fatal problems with mapping of
* content.
*<p>
* One additional feature is the ability to denote relevant path
* of references (during serialization/deserialization) to help in
* troubleshooting.
*/
public class JsonMappingException
extends JsonProcessingException
{
private static final long serialVersionUID = 1L;
/**
* Let's limit length of reference chain, to limit damage in cases
* of infinite recursion.
*/
final static int MAX_REFS_TO_LIST = 1000;
/*
/**********************************************************
/* Helper classes
/**********************************************************
*/
/**
* Simple bean class used to contain references. References
* can be added to indicate execution/reference path that
* lead to the problem that caused this exception to be
* thrown.
*/
public static class Reference implements Serializable
{
private static final long serialVersionUID = 1L;
/**
* Object through which reference was resolved. Can be either
* actual instance (usually the case for serialization), or
* Class (usually the case for deserialization).
*/
protected Object _from;
/**
* Name of field (for beans) or key (for Maps) that is part
* of the reference. May be null for Collection types (which
* generally have {@link #_index} defined), or when resolving
* Map classes without (yet) having an instance to operate on.
*/
protected String _fieldName;
/**
* Index within a {@link Collection} instance that contained
* the reference; used if index is relevant and available.
* If either not applicable, or not available, -1 is used to
* denote "not known".
*/
protected int _index = -1;
/**
* Default constructor for deserialization/sub-classing purposes
*/
protected Reference() { }
public Reference(Object from) { _from = from; }
public Reference(Object from, String fieldName) {
_from = from;
if (fieldName == null) {
throw new NullPointerException("Can not pass null fieldName");
}
_fieldName = fieldName;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> public Reference(Object from, int index) {
_from = from;
_index = index;
}
public void setFrom(Object o) { _from = o; }
public void setFieldName(String n) { _fieldName = n; }
public void setIndex(int ix) { _index = ix; }
public Object getFrom() { return _from; }
public String getFieldName() { return _fieldName; }
public int getIndex() { return _index; }
@Override public String toString() {
StringBuilder sb = new StringBuilder();
Class<?> cls = (_from instanceof Class<?>) ?
((Class<?>)_from) : _from.getClass();
/* Hmmh. Although Class.getName() is mostly ok, it does look
* butt-ugly for arrays. So let's use getSimpleName() instead;
* but have to prepend package name too.
*/
Package pkg = cls.getPackage();
if (pkg != null) {
sb.append(pkg.getName());
sb.append('.');
}
sb.append(cls.getSimpleName());
sb.append('[');
if (_fieldName != null) {
sb.append('"');
sb.append(_fieldName);
sb.append('"');
} else if (_index >= 0) {
sb.append(_index);
} else {
sb.append('?');
}
sb.append(']');
return sb.toString();
}
}
/*
/**********************************************************
/* State/configuration
/**********************************************************
*/
/**
* Path through which problem that triggering throwing of
* this exception was reached.
*/
protected LinkedList<Reference> _path;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
public JsonMappingException(String msg) { super(msg); }
public JsonMappingException(String msg, Throwable rootCause) { super(msg, rootCause); }
public JsonMappingException(String msg, JsonLocation loc) { super(msg, loc); }
public JsonMappingException(String msg, JsonLocation loc, Throwable rootCause) { super(msg, loc, rootCause); }
public static JsonMappingException from(JsonParser jp, String msg) {
return new JsonMappingException(msg, ((jp == null) ? null : jp.getTokenLocation()));
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
}
public static JsonMappingException from(JsonParser jp, String msg, Throwable problem) {
return new JsonMappingException(msg, ((jp == null) ? null : jp.getTokenLocation()), problem);
}
/**
* Factory method used when "upgrading" an {@link IOException} into
* {@link JsonMappingException}: usually only needed to comply with
* a signature.
*
* @since 2.1
*/
public static JsonMappingException fromUnexpectedIOE(IOException src) {
return new JsonMappingException("Unexpected IOException (of type "
+src.getClass().getName()+"): "+src.getMessage(), (JsonLocation)null, src);
}
/**
* Method that can be called to either create a new JsonMappingException
* (if underlying exception is not a JsonMappingException), or augment
* given exception with given path/reference information.
*
* This version of method is called when the reference is through a
* non-indexed object, such as a Map or POJO/bean.
*/
public static JsonMappingException wrapWithPath(Throwable src, Object refFrom,
String refFieldName) {
return wrapWithPath(src, new Reference(refFrom, refFieldName));
}
/**
* Method that can be called to either create a new JsonMappingException
* (if underlying exception is not a JsonMappingException), or augment
* given exception with given path/reference information.
*
* This version of method is called when the reference is through an
* index, which happens with arrays and Collections.
*/
public static JsonMappingException wrapWithPath(Throwable src, Object refFrom, int index) {
return wrapWithPath(src, new Reference(refFrom, index));
}
/**
* Method that can be called to either create a new JsonMappingException
* (if underlying exception is not a JsonMappingException), or augment
* given exception with given path/reference information.
*/
public static JsonMappingException wrapWithPath(Throwable src, Reference ref)
{
JsonMappingException jme;
if (src instanceof JsonMappingException) {
jme = (JsonMappingException) src;
} else {
String msg = src.getMessage();
/* Related to [JACKSON-62], let's use a more meaningful placeholder
* if all we have is
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> null
*/
if (msg == null || msg.length() == 0) {
msg = "(was "+src.getClass().getName()+")";
}
jme = new JsonMappingException(msg, null, src);
}
jme.prependPath(ref);
return jme;
}
/*
/**********************************************************
/* Accessors/mutators
/**********************************************************
*/
/**
* Method for accessing full structural path within type hierarchy
* down to problematic property.
*/
public List<Reference> getPath()
{
if (_path == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(_path);
}
/**
* Method for accesing description of path that lead to the
* problem that triggered this exception
*/
public String getPathReference()
{
return getPathReference(new StringBuilder()).toString();
}
public StringBuilder getPathReference(StringBuilder sb)
{
_appendPathDesc(sb);
return sb;
}
/**
* Method called to prepend a reference information in front of
* current path
*/
public void prependPath(Object referrer, String fieldName)
{
Reference ref = new Reference(referrer, fieldName);
prependPath(ref);
}
/**
* Method called to prepend a reference information in front of
* current path
*/
public void prependPath(Object referrer, int index)
{
Reference ref = new Reference(referrer, index);
prependPath(ref);
}
public void prependPath(Reference r)
{
if (_path == null) {
_path = new LinkedList<Reference>();
}
/* Also: let's not increase without bounds. Could choose either
* head or tail; tail is easier (no need to ever remove), as
* well as potentially more useful so let's use it:
*/
if (_path.size() < MAX_REFS_TO_LIST) {
_path.addFirst(r);
}
}
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public String getLocalizedMessage() {
return _buildMessage();
}
/**
* Method is overridden so that we can properly inject description
* of problem path, if such is defined.
*/
@Override
public String getMessage() {
return _buildMessage();
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>JavaType valueType, boolean staticTyping, EnumValues keyEnums,
TypeSerializer vts, JsonSerializer<Object> valueSerializer)
{
super(EnumMap.class, false);
_property = null; // not yet known
_staticTyping = staticTyping || (valueType != null && valueType.isFinal());
_valueType = valueType;
_keyEnums = keyEnums;
_valueTypeSerializer = vts;
_valueSerializer = valueSerializer;
}
/**
* Constructor called when a contextual instance is created.
*/
@SuppressWarnings("unchecked")
public EnumMapSerializer(EnumMapSerializer src, BeanProperty property,
JsonSerializer<?> ser)
{
super(src);
_property = property;
_staticTyping = src._staticTyping;
_valueType = src._valueType;
_keyEnums = src._keyEnums;
_valueTypeSerializer = src._valueTypeSerializer;
_valueSerializer = (JsonSerializer<Object>) ser;
}
@Override
public EnumMapSerializer _withValueTypeSerializer(TypeSerializer vts) {
return new EnumMapSerializer(_valueType, _staticTyping, _keyEnums, vts, _valueSerializer);
}
public EnumMapSerializer withValueSerializer(BeanProperty prop, JsonSerializer<?> ser) {
if (_property == prop && ser == _valueSerializer) {
return this;
}
return new EnumMapSerializer(this, prop, ser);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
* checking here since we finally know for sure the property,
* and it may have overrides
*/
JsonSerializer<?> ser = null;
// First: if we have a property, may have property-annotation overrides
if (property != null) {
AnnotatedMember m = property.getMember();
if (m != null) {
Object serDef = provider.getAnnotationIntrospector().findContentSerializer(m);
if (serDef != null) {
ser = provider.serializerInstance(m, serDef);
}
}
}
if (ser == null) {
ser = _valueSerializer;
}
// #124: May have a content
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>SerializationFeature.WRITE_NULL_MAP_VALUES);
final TypeSerializer vts = _valueTypeSerializer;
for (Map.Entry<? extends Enum<?>,?> entry : value.entrySet()) {
final Object valueElem = entry.getValue();
if (skipNulls && valueElem == null) { // [JACKSON-314] skip entries with null values?
continue;
}
// First, serialize key
Enum<?> key = entry.getKey();
if (keyEnums == null) {
/* 15-Oct-2009, tatu: This is clumsy, but still the simplest efficient
* way to do it currently, as Serializers get cached. (it does assume we'll always use
* default serializer tho -- so ideally code should be rewritten)
*/
// ... and lovely two-step casting process too...
StdSerializer<?> ser = (StdSerializer<?>) provider.findValueSerializer(
key.getDeclaringClass(), _property);
keyEnums = ((EnumSerializer) ser).getEnumValues();
}
jgen.writeFieldName(keyEnums.serializedValueFor(key));
if (valueElem == null) {
provider.defaultSerializeNull(jgen);
continue;
}
Class<?> cc = valueElem.getClass();
JsonSerializer<Object> currSerializer;
if (cc == prevClass) {
currSerializer = prevSerializer;
} else {
currSerializer = provider.findValueSerializer(cc, _property);
prevSerializer = currSerializer;
prevClass = cc;
}
try {
if (vts == null) {
currSerializer.serialize(valueElem, jgen, provider);
} else {
currSerializer.serializeWithType(valueElem, jgen, provider, vts);
}
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, entry.getKey().name());
}
}
}
protected void serializeContentsUsing(EnumMap<? extends Enum<?>,?> value, JsonGenerator jgen, SerializerProvider provider,
JsonSerializer<Object> valueSer)
throws IOException, JsonGenerationException
{
EnumValues keyEnums = _keyEnums;
final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>_MAP_VALUES);
final TypeSerializer vts = _valueTypeSerializer;
for (Map.Entry<? extends Enum<?>,?> entry : value.entrySet()) {
final Object valueElem = entry.getValue();
if (skipNulls && valueElem == null) { // [JACKSON-314] skip entries with null values?
continue;
}
Enum<?> key = entry.getKey();
if (keyEnums == null) {
// clumsy, but has to do for now:
StdSerializer<?> ser = (StdSerializer<?>) provider.findValueSerializer(key.getDeclaringClass(),
_property);
keyEnums = ((EnumSerializer) ser).getEnumValues();
}
jgen.writeFieldName(keyEnums.serializedValueFor(key));
if (valueElem == null) {
provider.defaultSerializeNull(jgen);
continue;
}
try {
if (vts == null) {
valueSer.serialize(valueElem, jgen, provider);
} else {
valueSer.serializeWithType(valueElem, jgen, provider, vts);
}
} catch (Exception e) {
wrapAndThrow(provider, e, value, entry.getKey().name());
}
}
}
@SuppressWarnings({ "unchecked", "deprecation" })
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
ObjectNode o = createSchemaNode("object", true);
if (typeHint instanceof ParameterizedType) {
Type[] typeArgs = ((ParameterizedType) typeHint).getActualTypeArguments();
if (typeArgs.length == 2) {
JavaType enumType = provider.constructType(typeArgs[0]);
JavaType valueType = provider.constructType(typeArgs[1]);
ObjectNode propsNode = JsonNodeFactory.instance.objectNode();
Class<Enum<?>> enumClass = (Class<Enum<?>>) enumType.getRawClass();
for (Enum<?> enumValue : enumClass.getEnumConstants()) {
JsonSerializer<Object> ser = provider.findValueSerializer(valueType.getRawClass(), _property);
JsonNode schemaNode = (ser instanceof SchemaAware) ?
((SchemaAware) ser).getSchema(provider, null) :
com.fasterxml.jackson.databind.jsonschema.JsonSchema.
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>getDefaultSchemaNode();
propsNode.put(provider.getConfig().getAnnotationIntrospector().findEnumValue((Enum<?>)enumValue), schemaNode);
}
o.put("properties", propsNode);
}
}
return o;
}
/**
* We consider possibility here that an EnumMap might actually just be serialized
* as something like a Record, given that number of keys is bound, just like
* with Objects/Records (and not unbounded like regular maps)
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
if (visitor == null) {
return;
}
JsonObjectFormatVisitor objectVisitor = visitor.expectObjectFormat(typeHint);
if (objectVisitor == null) {
return;
}
JavaType valueType = typeHint.containedType(1);
JsonSerializer<Object> ser = _valueSerializer;
if (ser == null && valueType != null) {
ser = visitor.getProvider().findValueSerializer(valueType, _property);
}
if (valueType == null) {
valueType = visitor.getProvider().constructType(Object.class);
}
EnumValues keyEnums = _keyEnums;
if (keyEnums == null) {
JavaType enumType = typeHint.containedType(0);
if (enumType == null) {
throw new IllegalStateException("Can not resolve Enum type of EnumMap: "+typeHint);
}
JsonSerializer<?> enumSer = visitor.getProvider().findValueSerializer(enumType, _property);
if (!(enumSer instanceof EnumSerializer)) {
throw new IllegalStateException("Can not resolve Enum type of EnumMap: "+typeHint);
}
keyEnums = ((EnumSerializer) enumSer).getEnumValues();
}
for (Map.Entry<?,SerializableString> entry : keyEnums.internalMap().entrySet()) {
String name = entry.getValue().getValue();
// should all have the same type, so:
if (ser == null) {
ser = visitor.getProvider().findValueSerializer(entry.getKey().getClass(), _property);
}
objectVisitor.property(name, (JsonFormatVisitable) ser, valueType);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
* Method called to check whether given serializable value is
* considered "empty" value (for purposes of suppressing serialization
* of empty values).
*<p>
* Default implementation will consider only null values to be empty.
*
* @since 2.0
*/
public boolean isEmpty(T value) {
return (value == null);
}
/**
* Method that can be called to see whether this serializer instance
* will use Object Id to handle cyclic references.
*/
public boolean usesObjectId() {
return false;
}
/**
* Accessor for checking whether this serializer is an
* "unwrapping" serializer; this is necessary to know since
* it may also require caller to suppress writing of the
* leading property name.
*/
public boolean isUnwrappingSerializer() {
return false;
}
/**
* Accessor that can be used to determine if this serializer uses
* another serializer for actual serialization, by delegating
* calls. If so, will return immediate delegate (which itself may
* delegate to further serializers); otherwise will return null.
*
* @return Serializer this serializer delegates calls to, if null;
* null otherwise.
*
* @since 2.1
*/
public JsonSerializer<?> getDelegatee() {
return null;
}
/*
/**********************************************************
/* Default JsonFormatVisitable implementation
/**********************************************************
*/
/**
* Default implementation simply calls {@link JsonFormatVisitorWrapper#expectAnyFormat(JavaType)}.
*
* @since 2.1
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type)
throws JsonMappingException
{
if (visitor != null) visitor.expectAnyFormat(type);
}
/*
/**********************************************************
/* Helper class(es)
/**********************************************************
*/
/**
* This marker class is only to be used with annotations, to
* indicate that <b>no serializer is configured</b>.
*<p>
* Specifically, this class is to be used as the marker for
* annotation {@link com.fasterxml.jackson.databind.annotation.JsonSerialize}.
*/
public abstract static class None
extends JsonSerializer<Object> { }
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
public abstract class StdScalarSerializer<T>
extends StdSerializer<T>
{
protected StdScalarSerializer(Class<T> t) {
super(t);
}
/**
* Alternate constructor that is (alas!) needed to work
* around kinks of generic type handling
*/
@SuppressWarnings("unchecked")
protected StdScalarSerializer(Class<?> t, boolean dummy) {
super((Class<T>) t);
}
/**
* Default implementation will write type prefix, call regular serialization
* method (since assumption is that value itself does not need JSON
* Array or Object start/end markers), and then write type suffix.
* This should work for most cases; some sub-classes may want to
* change this behavior.
*/
@Override
public void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonGenerationException
{
typeSer.writeTypePrefixForScalar(value, jgen);
serialize(value, jgen, provider);
typeSer.writeTypeSuffixForScalar(value, jgen);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
if (visitor != null) {
// 13-Sep-2013, tatu: Let's assume it's usually a String, right?
// visitor.expectAnyFormat(typeHint);
visitor.expectStringFormat(typeHint);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Interface used to indicate deserializers that want to do post-processing
* after construction but before being returned to caller (and possibly cached)
* and used.
* This is typically used to resolve references
* to other contained types; for example, bean deserializers use this callback
* to locate deserializers for contained field types.
* Main reason for using a callback (instead of trying to resolve dependencies
* immediately) is to make it possible to cleanly handle self-references;
* otherwise it would be easy to get into infinite recursion.
*<p>
* Note that {@link #resolve} method does NOT allow returning anything
* (specifically, a new deserializer instance): reason for this is that
* allowing this would not work with proper handling of cyclic dependencies,
* which are resolved by two-phase processing, where initially constructed
* deserializer is added as known deserializer, and only after this
* resolution is done. Resolution is the part that results in lookups for
* dependant deserializers, which may include handling references to
* deserializer itself.
*<p>
* Note that in cases where deserializer needs both contextualization and
* resolution -- that is, implements both this interface and {@link ContextualDeserializer}
* -- resolution via this interface occurs first, and contextual
* resolution (using {@link ContextualDeserializer}) later on.
*/
public interface ResolvableDeserializer
{
/**
* Method called after deserializer instance has been constructed
* (and registered as necessary by provider objects),
* but before it has returned it to the caller.
* Called object can then resolve its dependencies to other types,
* including self-references (direct or indirect).
*
* @param ctxt Context to use for accessing configuration, resolving
* secondary deserializers
*/
public abstract void resolve(DeserializationContext ctxt)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> serializeContentsUsing(value, jgen, provider, _elementSerializer);
return;
}
if (_valueTypeSerializer != null) {
serializeTypedContents(value, jgen, provider);
return;
}
final int len = value.size();
if (len == 0) {
return;
}
int i = 0;
try {
PropertySerializerMap serializers = _dynamicSerializers;
for (; i < len; ++i) {
Object elem = value.get(i);
if (elem == null) {
provider.defaultSerializeNull(jgen);
} else {
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
// To fix [JACKSON-508]
if (_elementType.hasGenericTypes()) {
serializer = _findAndAddDynamic(serializers,
provider.constructSpecializedType(_elementType, cc), provider);
} else {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
serializers = _dynamicSerializers;
}
serializer.serialize(elem, jgen, provider);
}
}
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, i);
}
}
public void serializeContentsUsing(List<?> value, JsonGenerator jgen, SerializerProvider provider,
JsonSerializer<Object> ser)
throws IOException, JsonGenerationException
{
final int len = value.size();
if (len == 0) {
return;
}
final TypeSerializer typeSer = _valueTypeSerializer;
for (int i = 0; i < len; ++i) {
Object elem = value.get(i);
try {
if (elem == null) {
provider.defaultSerializeNull(jgen);
} else if (typeSer == null) {
ser.serialize(elem, jgen, provider);
} else {
ser.serializeWithType(elem, jgen, provider, typeSer);
}
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, i);
}
}
}
public void serializeTyped
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Contents(List<?> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
final int len = value.size();
if (len == 0) {
return;
}
int i = 0;
try {
final TypeSerializer typeSer = _valueTypeSerializer;
PropertySerializerMap serializers = _dynamicSerializers;
for (; i < len; ++i) {
Object elem = value.get(i);
if (elem == null) {
provider.defaultSerializeNull(jgen);
} else {
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
// To fix [JACKSON-508]
if (_elementType.hasGenericTypes()) {
serializer = _findAndAddDynamic(serializers,
provider.constructSpecializedType(_elementType, cc), provider);
} else {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
serializers = _dynamicSerializers;
}
serializer.serializeWithType(elem, jgen, provider, typeSer);
}
}
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, i);
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> /**
* Method that will introspect subset of bean properties needed to
* construct bean instance.
*/
@SuppressWarnings("unchecked")
public <T extends BeanDescription> T introspectForCreation(JavaType type) {
return (T) getClassIntrospector().forCreation(this, type, this);
}
/**
* @since 2.0
*/
@SuppressWarnings("unchecked")
public <T extends BeanDescription> T introspectForBuilder(JavaType type) {
return (T) getClassIntrospector().forDeserializationWithBuilder(this, type, this);
}
/*
/**********************************************************
/* Support for polymorphic type handling
/**********************************************************
*/
/**
* Helper method that is needed to properly handle polymorphic referenced
* types, such as types referenced by {@link java.util.concurrent.atomic.AtomicReference},
* or various "optional" types.
*
* @since 2.4
*/
public TypeDeserializer findTypeDeserializer(JavaType baseType)
throws JsonMappingException
{
BeanDescription bean = introspectClassAnnotations(baseType.getRawClass());
AnnotatedClass ac = bean.getClassInfo();
TypeResolverBuilder<?> b = getAnnotationIntrospector().findTypeResolver(this, ac, baseType);
/* Ok: if there is no explicit type info handler, we may want to
* use a default. If so, config object knows what to use.
*/
Collection<NamedType> subtypes = null;
if (b == null) {
b = getDefaultTyper(baseType);
if (b == null) {
return null;
}
} else {
subtypes = getSubtypeResolver().collectAndResolveSubtypes(ac, this, getAnnotationIntrospector());
}
/* 04-May-2014, tatu: When called from DeserializerFactory, additional code like
* this is invoked. But here we do not actually have access to mappings, so not
* quite sure what to do, if anything. May need to revisit if the underlying
* problem re-surfaces...
*/
/*
if ((b.getDefaultImpl() == null) && baseType.isAbstract()) {
JavaType defaultType = mapAbstractType(config, baseType);
if (defaultType != null && defaultType.
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> /* Serialization
/**********************************************************
*/
@Override
public abstract void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException;
/*
/**********************************************************
/* Helper methods for JSON Schema generation
/**********************************************************
*/
/**
* Default implementation simply claims type is "string"; usually
* overriden by custom serializers.
*/
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
return createSchemaNode("string");
}
/**
* Default implementation simply claims type is "string"; usually
* overriden by custom serializers.
*/
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint, boolean isOptional)
throws JsonMappingException
{
ObjectNode schema = (ObjectNode) getSchema(provider, typeHint);
if (!isOptional) {
schema.put("required", !isOptional);
}
return schema;
}
protected ObjectNode createObjectNode() {
return JsonNodeFactory.instance.objectNode();
}
protected ObjectNode createSchemaNode(String type)
{
ObjectNode schema = createObjectNode();
schema.put("type", type);
return schema;
}
protected ObjectNode createSchemaNode(String type, boolean isOptional)
{
ObjectNode schema = createSchemaNode(type);
// as per [JACKSON-563]. Note that 'required' defaults to false
if (!isOptional) {
schema.put("required", !isOptional);
}
return schema;
}
/**
* Default implementation specifies no format. This behavior is usually
* overriden by custom serializers.
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
visitor.expectAnyFormat(typeHint);
}
/*
/**********************************************************
/* Helper methods for exception handling
/**********************************************************
*/
/**
* Method that will modify caught exception (passed in as argument)
* as necessary to include reference information, and to ensure it
* is a subtype of {@link IOException}, or an unchecked exception.
*<p>
* Rules for wrapping and unwrapping are bit complicated; essentially:
*<ul>
* <li>Errors are
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> to be passed as is (if uncovered via unwrapping)
* <li>"Plain" IOExceptions (ones that are not of type
* {@link JsonMappingException} are to be passed as is
*</ul>
*/
public void wrapAndThrow(SerializerProvider provider,
Throwable t, Object bean, String fieldName)
throws IOException
{
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that
* usually gets hidden within an InvocationTargetException...
*/
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// Ditto for IOExceptions... except for mapping exceptions!
boolean wrap = (provider == null) || provider.isEnabled(SerializationFeature.WRAP_EXCEPTIONS);
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
}
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(t, bean, fieldName);
}
public void wrapAndThrow(SerializerProvider provider,
Throwable t, Object bean, int index)
throws IOException
{
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors are to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// Ditto for IOExceptions... except for mapping exceptions!
boolean wrap = (provider == null) || provider.isEnabled(SerializationFeature.WRAP_EXCEPTIONS);
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
} else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
if (t instanceof RuntimeException) {
throw
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> (RuntimeException) t;
}
}
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(t, bean, index);
}
/*
/**********************************************************
/* Helper methods, other
/**********************************************************
*/
/**
* Method that can be called to determine if given serializer is the default
* serializer Jackson uses; as opposed to a custom serializer installed by
* a module or calling application. Determination is done using
* {@link JacksonStdImpl} annotation on serializer class.
*/
protected boolean isDefaultSerializer(JsonSerializer<?> serializer) {
return ClassUtil.isJacksonStdImpl(serializer);
}
/**
* Helper method that can be used to see if specified property has annotation
* indicating that a converter is to be used for contained values (contents
* of structured types; array/List/Map values)
*
* @param existingSerializer (optional) configured content
* serializer if one already exists.
*
* @since 2.2
*/
protected JsonSerializer<?> findConvertingContentSerializer(SerializerProvider provider,
BeanProperty prop, JsonSerializer<?> existingSerializer)
throws JsonMappingException
{
final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
if (intr != null && prop != null) {
Object convDef = intr.findSerializationContentConverter(prop.getMember());
if (convDef != null) {
Converter<Object,Object> conv = provider.converterInstance(prop.getMember(), convDef);
JavaType delegateType = conv.getOutputType(provider.getTypeFactory());
if (existingSerializer == null) {
existingSerializer = provider.findValueSerializer(delegateType, prop);
}
return new StdDelegatingSerializer(conv, delegateType, existingSerializer);
}
}
return existingSerializer;
}
/**
* Helper method used to locate filter that is needed, based on filter id
* this serializer was constructed with.
*
* @since 2.3
*/
protected PropertyFilter findPropertyFilter(SerializerProvider provider,
Object filterId, Object valueToFilter)
throws JsonMappingException
{
FilterProvider filters = provider.getFilterProvider();
// Not ok to miss the provider, if a filter is declared to be needed.
if (filters == null) {
throw new
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> JsonMappingException("Can not resolve PropertyFilter with id '"+filterId+"'; no FilterProvider configured");
}
PropertyFilter filter = filters.findPropertyFilter(filterId, valueToFilter);
// But whether unknown ids are ok just depends on filter provider; if we get null that's fine
return filter;
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> instances, where we do not yet know
* which property is using this deserializer.
*/
public CollectionDeserializer(JavaType collectionType,
JsonDeserializer<Object> valueDeser,
TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator)
{
this(collectionType, valueDeser, valueTypeDeser, valueInstantiator, null);
}
/**
* Constructor used when creating contextualized instances.
*/
protected CollectionDeserializer(JavaType collectionType,
JsonDeserializer<Object> valueDeser, TypeDeserializer valueTypeDeser,
ValueInstantiator valueInstantiator,
JsonDeserializer<Object> delegateDeser)
{
super(collectionType);
_collectionType = collectionType;
_valueDeserializer = valueDeser;
_valueTypeDeserializer = valueTypeDeser;
_valueInstantiator = valueInstantiator;
_delegateDeserializer = delegateDeser;
}
/**
* Copy-constructor that can be used by sub-classes to allow
* copy-on-write styling copying of settings of an existing instance.
*/
protected CollectionDeserializer(CollectionDeserializer src)
{
super(src._collectionType);
_collectionType = src._collectionType;
_valueDeserializer = src._valueDeserializer;
_valueTypeDeserializer = src._valueTypeDeserializer;
_valueInstantiator = src._valueInstantiator;
_delegateDeserializer = src._delegateDeserializer;
}
/**
* Fluent-factory method call to construct contextual instance.
*/
@SuppressWarnings("unchecked")
protected CollectionDeserializer withResolved(JsonDeserializer<?> dd,
JsonDeserializer<?> vd, TypeDeserializer vtd)
{
if ((dd == _delegateDeserializer) && (vd == _valueDeserializer) && (vtd == _valueTypeDeserializer)) {
return this;
}
return new CollectionDeserializer(_collectionType,
(JsonDeserializer<Object>) vd, vtd,
_valueInstantiator, (JsonDeserializer<Object>) dd);
}
/*
/**********************************************************
/* Validation, post-processing (ResolvableDeserializer)
/**********************************************************
*/
/**
* Method called to finalize setup of this deserializer,
* when it is known for which property deserializer is needed
* for.
*/
@Override
public CollectionDeserializer createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
// May need
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> be ok; bit tricky to check, however, since
* there is also possibility of "auto-wrapping" of single-element arrays.
* Hence we only accept empty String here.
*/
if (jp.getCurrentToken() == JsonToken.VALUE_STRING) {
String str = jp.getText();
if (str.length() == 0) {
return (Collection<Object>) _valueInstantiator.createFromString(ctxt, str);
}
}
return deserialize(jp, ctxt, (Collection<Object>) _valueInstantiator.createUsingDefault(ctxt));
}
@Override
public Collection<Object> deserialize(JsonParser jp, DeserializationContext ctxt,
Collection<Object> result)
throws IOException, JsonProcessingException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt, result);
}
JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
CollectionReferringAccumulator referringAccumulator =
(valueDes.getObjectIdReader() == null) ? null :
new CollectionReferringAccumulator(_collectionType.getContentType().getRawClass(), result);
JsonToken t;
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
try {
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
if (referringAccumulator != null) {
referringAccumulator.add(value);
} else {
result.add(value);
}
} catch (UnresolvedForwardReference reference) {
if (referringAccumulator == null) {
throw JsonMappingException
.from(jp, "Unresolved forward reference but no identity info.", reference);
}
Referring ref = referringAccumulator.handleUnresolvedReference(reference);
reference.getRoid().appendReferring(ref);
} catch (Exception e) {
// note: pass Object.class, not Object[].class, as we need element type for error info
throw JsonMappingException
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>.wrapWithPath(e, Object.class, result.size());
}
}
return result;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
/**
* Helper method called when current token is no START_ARRAY. Will either
* throw an exception, or try to handle value as if member of implicit
* array, depending on configuration.
*/
protected final Collection<Object> handleNonArray(JsonParser jp, DeserializationContext ctxt,
Collection<Object> result)
throws IOException, JsonProcessingException
{
// [JACKSON-526]: implicit arrays from single values?
if (!ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
throw ctxt.mappingException(_collectionType.getRawClass());
}
JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
JsonToken t = jp.getCurrentToken();
Object value;
try {
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(jp, ctxt);
} else {
value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
}
} catch (Exception e) {
// note: pass Object.class, not Object[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, Object.class, result.size());
}
result.add(value);
return result;
}
public final static class CollectionReferringAccumulator {
private final Class<?> _elementType;
private final Collection<Object> _result;
/**
* A list of {@link CollectionReferring} to maintain ordering.
*/
private List<CollectionReferring> _accumulator = new ArrayList<CollectionReferring>();
public CollectionReferringAccumulator(Class<?> elementType, Collection<Object> result) {
_elementType = elementType;
_result = result;
}
public void add(Object value)
{
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> classes and
* interfaces, to avoid having to use exact types or annotations in
* cases where the most common concrete Maps will do.
*/
@SuppressWarnings("rawtypes")
final static HashMap<String, Class<? extends Map>> _mapFallbacks =
new HashMap<String, Class<? extends Map>>();
static {
_mapFallbacks.put(Map.class.getName(), LinkedHashMap.class);
_mapFallbacks.put(ConcurrentMap.class.getName(), ConcurrentHashMap.class);
_mapFallbacks.put(SortedMap.class.getName(), TreeMap.class);
/* 11-Jan-2009, tatu: Let's see if we can still add support for
* JDK 1.6 interfaces, even if we run on 1.5. Just need to be
* more careful with typos, since compiler won't notice any
* problems...
*/
_mapFallbacks.put("java.util.NavigableMap", TreeMap.class);
try {
Class<?> key = java.util.concurrent.ConcurrentNavigableMap.class;
Class<?> value = java.util.concurrent.ConcurrentSkipListMap.class;
@SuppressWarnings("unchecked")
Class<? extends Map<?,?>> mapValue = (Class<? extends Map<?,?>>) value;
_mapFallbacks.put(key.getName(), mapValue);
} catch (Throwable e) { // some class loading problems are Errors, others Exceptions
System.err.println("Problems with (optional) types: "+e);
}
}
/* We do some defaulting for abstract Collection classes and
* interfaces, to avoid having to use exact types or annotations in
* cases where the most common concrete Collection will do.
*/
@SuppressWarnings("rawtypes")
final static HashMap<String, Class<? extends Collection>> _collectionFallbacks =
new HashMap<String, Class<? extends Collection>>();
static {
_collectionFallbacks.put(Collection.class.getName(), ArrayList.class);
_collectionFallbacks.put(List.class.getName(), ArrayList.class);
_collectionFallbacks.put(Set.class.getName(), HashSet.class);
_collectionFallbacks.put(SortedSet.class.getName(), TreeSet.class);
_collectionFallbacks.put(Queue.class.getName(), LinkedList.class);
//
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> new factory instance with additional
* {@link AbstractTypeResolver}.
*/
@Override
public final DeserializerFactory withAbstractTypeResolver(AbstractTypeResolver resolver) {
return withConfig(_factoryConfig.withAbstractTypeResolver(resolver));
}
/**
* Convenience method for creating a new factory instance with additional
* {@link ValueInstantiators}.
*/
@Override
public final DeserializerFactory withValueInstantiators(ValueInstantiators instantiators) {
return withConfig(_factoryConfig.withValueInstantiators(instantiators));
}
/*
/**********************************************************
/* JsonDeserializerFactory impl (partial): type mappings
/**********************************************************
*/
@Override
public JavaType mapAbstractType(DeserializationConfig config, JavaType type)
throws JsonMappingException
{
// first, general mappings
while (true) {
JavaType next = _mapAbstractType2(config, type);
if (next == null) {
return type;
}
/* Should not have to worry about cycles; but better verify since they will invariably
* occur... :-)
* (also: guard against invalid resolution to a non-related type)
*/
Class<?> prevCls = type.getRawClass();
Class<?> nextCls = next.getRawClass();
if ((prevCls == nextCls) || !prevCls.isAssignableFrom(nextCls)) {
throw new IllegalArgumentException("Invalid abstract type resolution from "+type+" to "+next+": latter is not a subtype of former");
}
type = next;
}
}
/**
* Method that will find abstract type mapping for specified type, doing a single
* lookup through registered abstract type resolvers; will not do recursive lookups.
*/
private JavaType _mapAbstractType2(DeserializationConfig config, JavaType type)
throws JsonMappingException
{
Class<?> currClass = type.getRawClass();
if (_factoryConfig.hasAbstractTypeResolvers()) {
for (AbstractTypeResolver resolver : _factoryConfig.abstractTypeResolvers()) {
JavaType concrete = resolver.findTypeMapping(config, type);
if (concrete != null && concrete.getRawClass() != currClass) {
return concrete;
}
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl (partial): ValueInstantiators
/**********************************************************
*/
/**
* Value instantiator is
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> created both based on creator annotations,
* and on optional externally provided instantiators (registered through
* module interface).
*/
@Override
public ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
BeanDescription beanDesc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
ValueInstantiator instantiator = null;
// [JACKSON-633] Check @JsonValueInstantiator before anything else
AnnotatedClass ac = beanDesc.getClassInfo();
Object instDef = ctxt.getAnnotationIntrospector().findValueInstantiator(ac);
if (instDef != null) {
instantiator = _valueInstantiatorInstance(config, ac, instDef);
}
if (instantiator == null) {
/* Second: see if some of standard Jackson/JDK types might provide value
* instantiators.
*/
instantiator = _findStdValueInstantiator(config, beanDesc);
if (instantiator == null) {
instantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);
}
}
// finally: anyone want to modify ValueInstantiator?
if (_factoryConfig.hasValueInstantiators()) {
for (ValueInstantiators insts : _factoryConfig.valueInstantiators()) {
instantiator = insts.findValueInstantiator(config, beanDesc, instantiator);
// let's do sanity check; easier to spot buggy handlers
if (instantiator == null) {
throw new JsonMappingException("Broken registered ValueInstantiators (of type "
+insts.getClass().getName()+"): returned null ValueInstantiator");
}
}
}
// Sanity check: does the chosen instantatior have incomplete creators?
if (instantiator.getIncompleteParameter() != null) {
final AnnotatedParameter nonAnnotatedParam = instantiator.getIncompleteParameter();
final AnnotatedWithParams ctor = nonAnnotatedParam.getOwner();
throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()+" of constructor "+ctor+" has no property name annotation; must have name when multiple-parameter constructor annotated as Creator");
}
return instantiator;
}
private ValueInstantiator _findStdValueInstantiator(DeserializationConfig config,
BeanDescription beanDesc)
throws JsonMappingException
{
if (beanDesc.getBeanClass() == JsonLocation.class)
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> {
return new JsonLocationInstantiator();
}
return null;
}
/**
* Method that will construct standard default {@link ValueInstantiator}
* using annotations (like @JsonCreator) and visibility rules
*/
protected ValueInstantiator _constructDefaultValueInstantiator(DeserializationContext ctxt,
BeanDescription beanDesc)
throws JsonMappingException
{
boolean fixAccess = ctxt.canOverrideAccessModifiers();
CreatorCollector creators = new CreatorCollector(beanDesc, fixAccess);
AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
// need to construct suitable visibility checker:
final DeserializationConfig config = ctxt.getConfig();
VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker();
vchecker = intr.findAutoDetectVisibility(beanDesc.getClassInfo(), vchecker);
/* Important: first add factory methods; then constructors, so
* latter can override former!
*/
_addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators);
// constructors only usable on concrete types:
if (beanDesc.getType().isConcrete()) {
_addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators);
}
return creators.constructValueInstantiator(config);
}
public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config,
Annotated annotated, Object instDef)
throws JsonMappingException
{
if (instDef == null) {
return null;
}
ValueInstantiator inst;
if (instDef instanceof ValueInstantiator) {
return (ValueInstantiator) instDef;
}
if (!(instDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
+instDef.getClass().getName()
+"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
}
Class<?> instClass = (Class<?>)instDef;
if (ClassUtil.isBogusClass(instClass)) {
return null;
}
if (!ValueInstantiator.class.isAssignableFrom(instClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "+instClass.getName()
+"; expected Class<ValueInstantiator>");
}
HandlerInstantiator hi = config.getHandlerInstantiator();
if (hi != null) {
inst = hi.valueInstantiatorInstance(
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>config, annotated, instClass);
if (inst != null) {
return inst;
}
}
return (ValueInstantiator) ClassUtil.createInstance(instClass,
config.canOverrideAccessModifiers());
}
protected void _addDeserializerConstructors
(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
AnnotationIntrospector intr, CreatorCollector creators)
throws JsonMappingException
{
/* First things first: the "default constructor" (zero-arg
* constructor; whether implicit or explicit) is NOT included
* in list of constructors, so needs to be handled separately.
*/
AnnotatedConstructor defaultCtor = beanDesc.findDefaultConstructor();
if (defaultCtor != null) {
if (!creators.hasDefaultCreator() || intr.hasCreatorAnnotation(defaultCtor)) {
creators.setDefaultCreator(defaultCtor);
}
}
PropertyName[] ctorPropNames = null;
AnnotatedConstructor propertyCtor = null;
for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
if (propDef.getConstructorParameter() != null) {
AnnotatedParameter param = propDef.getConstructorParameter();
AnnotatedWithParams owner = param.getOwner();
if (owner instanceof AnnotatedConstructor) {
if (propertyCtor == null) {
propertyCtor = (AnnotatedConstructor) owner;
ctorPropNames = new PropertyName[propertyCtor.getParameterCount()];
}
ctorPropNames[param.getIndex()] = propDef.getFullName();
}
}
}
for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
int argCount = ctor.getParameterCount();
boolean isCreator = intr.hasCreatorAnnotation(ctor) || ctor == propertyCtor;
boolean isVisible = vchecker.isCreatorVisible(ctor);
// some single-arg constructors (String, number) are auto-detected
if (argCount == 1) {
PropertyName name = (ctor == propertyCtor) ? ctorPropNames[0] : null;
_handleSingleArgumentConstructor(ctxt, beanDesc, vchecker, intr, creators,
ctor, isCreator, isVisible, name);
continue;
}
if (!isCreator && !isVisible) {
continue;
}
// [JACKSON-541] improved handling a bit so:
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>-named)
creators.addDelegatingCreator(ctor, properties);
} else { // otherwise, record the incomplete parameter for later error messaging.
creators.addIncompeteParameter(nonAnnotatedParam);
}
}
}
}
protected boolean _handleSingleArgumentConstructor(DeserializationContext ctxt,
BeanDescription beanDesc, VisibilityChecker<?> vchecker,
AnnotationIntrospector intr, CreatorCollector creators,
AnnotatedConstructor ctor, boolean isCreator, boolean isVisible,
PropertyName name)
throws JsonMappingException
{
// note: if we do have parameter name, it'll be "property constructor":
AnnotatedParameter param = ctor.getParameter(0);
if (name == null) {
name = _findParamName(param, intr);
}
Object injectId = intr.findInjectableValueId(param);
if ((injectId != null) || (name != null && name.hasSimpleName())) { // property-based
// We know there's a name and it's only 1 parameter.
CreatorProperty[] properties = new CreatorProperty[1];
properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0, param, injectId);
creators.addPropertyCreator(ctor, properties);
return true;
}
// otherwise either 'simple' number, String, or general delegate:
Class<?> type = ctor.getRawParameterType(0);
if (type == String.class) {
if (isCreator || isVisible) {
creators.addStringCreator(ctor);
}
return true;
}
if (type == int.class || type == Integer.class) {
if (isCreator || isVisible) {
creators.addIntCreator(ctor);
}
return true;
}
if (type == long.class || type == Long.class) {
if (isCreator || isVisible) {
creators.addLongCreator(ctor);
}
return true;
}
if (type == double.class || type == Double.class) {
if (isCreator || isVisible) {
creators.addDoubleCreator(ctor);
}
return true;
}
if (type == boolean.class || type == Boolean.class) {
if (isCreator || isVisible) {
creators.addBooleanCreator(ctor);
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
}
return true;
}
// Delegating Creator ok iff it has @JsonCreator (etc)
if (isCreator) {
creators.addDelegatingCreator(ctor, null);
return true;
}
return false;
}
protected void _addDeserializerFactoryMethods
(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
AnnotationIntrospector intr, CreatorCollector creators)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
boolean isCreator = intr.hasCreatorAnnotation(factory);
int argCount = factory.getParameterCount();
// zero-arg methods must be annotated; if so, are "default creators" [JACKSON-850]
if (argCount == 0) {
if (isCreator) {
creators.setDefaultCreator(factory);
}
continue;
}
// some single-arg factory methods (String, number) are auto-detected
if (argCount == 1) {
AnnotatedParameter param = factory.getParameter(0);
PropertyName pn = _findParamName(param, intr);
String name = (pn == null) ? null : pn.getSimpleName();
Object injectId = intr.findInjectableValueId(param);
if ((injectId == null) && (name == null || name.length() == 0)) { // not property based
_handleSingleArgumentFactory(config, beanDesc, vchecker, intr, creators,
factory, isCreator);
// otherwise just ignored
continue;
}
// fall through if there's name
} else {
// more than 2 args, must be @JsonCreator
if (!intr.hasCreatorAnnotation(factory)) {
continue;
}
}
// 1 or more args; all params must have name annotations
AnnotatedParameter nonAnnotatedParam = null;
CreatorProperty[] properties = new CreatorProperty[argCount];
int namedCount = 0;
int injectCount = 0;
for (int i = 0; i < argCount; ++i) {
AnnotatedParameter param = factory.getParameter(i);
PropertyName name = _findParamName(param, intr);
Object injectId = intr.findInjectableValueId(param);
if
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> (name != null && name.hasSimpleName()) {
++namedCount;
properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
} else if (injectId != null) {
++injectCount;
properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
} else {
NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
if (unwrapper != null) {
properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
++namedCount;
} else {
if (nonAnnotatedParam == null) {
nonAnnotatedParam = param;
}
}
}
}
// Ok: if named or injectable, we have more work to do
if (isCreator || namedCount > 0 || injectCount > 0) {
// simple case; everything covered:
if ((namedCount + injectCount) == argCount) {
creators.addPropertyCreator(factory, properties);
} else if ((namedCount == 0) && ((injectCount + 1) == argCount)) {
// [712] secondary: all but one injectable, one un-annotated (un-named)
creators.addDelegatingCreator(factory, properties);
} else { // otherwise, epic fail
throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()
+" of factory method "+factory+" has no property name annotation; must have name when multiple-parameter constructor annotated as Creator");
}
}
}
}
protected boolean _handleSingleArgumentFactory(DeserializationConfig config,
BeanDescription beanDesc, VisibilityChecker<?> vchecker,
AnnotationIntrospector intr, CreatorCollector creators,
AnnotatedMethod factory, boolean isCreator)
throws JsonMappingException
{
Class<?> type = factory.getRawParameterType(0);
if (type == String.class) {
if (isCreator || vchecker.isCreatorVisible(factory)) {
creators.addStringCreator(factory);
}
return true;
}
if (type == int.class || type == Integer.class) {
if (isCreator || vchecker.isCreatorVisible(factory)) {
creators.add
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>IntCreator(factory);
}
return true;
}
if (type == long.class || type == Long.class) {
if (isCreator || vchecker.isCreatorVisible(factory)) {
creators.addLongCreator(factory);
}
return true;
}
if (type == double.class || type == Double.class) {
if (isCreator || vchecker.isCreatorVisible(factory)) {
creators.addDoubleCreator(factory);
}
return true;
}
if (type == boolean.class || type == Boolean.class) {
if (isCreator || vchecker.isCreatorVisible(factory)) {
creators.addBooleanCreator(factory);
}
return true;
}
if (intr.hasCreatorAnnotation(factory)) {
creators.addDelegatingCreator(factory, null);
return true;
}
return false;
}
/**
* Method that will construct a property object that represents
* a logical property passed via Creator (constructor or static
* factory method)
*/
protected CreatorProperty constructCreatorProperty(DeserializationContext ctxt,
BeanDescription beanDesc, PropertyName name, int index,
AnnotatedParameter param,
Object injectableValueId)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
PropertyMetadata metadata;
{
Boolean b = (intr == null) ? null : intr.hasRequiredMarker(param);
boolean req = (b != null && b.booleanValue());
String desc = (intr == null) ? null : intr.findPropertyDescription(param);
Integer idx = (intr == null) ? null : intr.findPropertyIndex(param);
metadata = PropertyMetadata.construct(req, desc, idx);
}
JavaType t0 = config.getTypeFactory().constructType(param.getParameterType(), beanDesc.bindingsForBeanType());
BeanProperty.Std property = new BeanProperty.Std(name, t0,
intr.findWrapperName(param),
beanDesc.getClassAnnotations(), param, metadata);
JavaType type = resolveType(ctxt, beanDesc, t0, param);
if (type != t0) {
property = property.withType(type);
}
// Is there an annotation
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> that specifies exact deserializer?
JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, param);
// If yes, we are mostly done:
type = modifyTypeByAnnotation(ctxt, param, type);
// Type deserializer: either comes from property (and already resolved)
TypeDeserializer typeDeser = (TypeDeserializer) type.getTypeHandler();
// or if not, based on type being referenced:
if (typeDeser == null) {
typeDeser = findTypeDeserializer(config, type);
}
// Note: contextualization of typeDeser _should_ occur in constructor of CreatorProperty
// so it is not called directly here
CreatorProperty prop = new CreatorProperty(name, type, property.getWrapperName(),
typeDeser, beanDesc.getClassAnnotations(), param, index, injectableValueId,
metadata);
if (deser != null) {
// As per [Issue#462] need to ensure we contextualize deserializer before passing it on
deser = ctxt.handlePrimaryContextualization(deser, prop);
prop = prop.withValueDeserializer(deser);
}
return prop;
}
protected PropertyName _findParamName(AnnotatedParameter param, AnnotationIntrospector intr)
{
if (param != null && intr != null) {
PropertyName name = intr.findNameForDeserialization(param);
if (name != null) {
return name;
}
/* 14-Apr-2014, tatu: Need to also consider possible implicit name
* (for JDK8, or via paranamer)
*/
String str = intr.findImplicitPropertyName(param);
if (str != null && !str.isEmpty()) {
return new PropertyName(str);
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl: array deserializers
/**********************************************************
*/
@Override
public JsonDeserializer<?> createArrayDeserializer(DeserializationContext ctxt,
ArrayType type, final BeanDescription beanDesc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
JavaType elemType = type.getContentType();
// Very first thing: is deserializer hard-coded for elements?
JsonDeserializer<Object> contentDeser = elemType.getValueHandler();
// Then optional type
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> info (1.5): if type has been resolved, we may already know type deserializer:
TypeDeserializer elemTypeDeser = elemType.getTypeHandler();
// but if not, may still be possible to find:
if (elemTypeDeser == null) {
elemTypeDeser = findTypeDeserializer(config, elemType);
}
// 23-Nov-2010, tatu: Custom array deserializer?
JsonDeserializer<?> deser = _findCustomArrayDeserializer(type,
config, beanDesc, elemTypeDeser, contentDeser);
if (deser == null) {
if (contentDeser == null) {
Class<?> raw = elemType.getRawClass();
if (elemType.isPrimitive()) {
return PrimitiveArrayDeserializers.forType(raw);
} else if (raw == String.class) {
return StringArrayDeserializer.instance;
}
}
deser = new ObjectArrayDeserializer(type, contentDeser, elemTypeDeser);
}
// and then new with 2.2: ability to post-process it too (Issue#120)
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyArrayDeserializer(config, type, beanDesc, deser);
}
}
return deser;
}
protected JsonDeserializer<?> _findCustomArrayDeserializer(ArrayType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findArrayDeserializer(type, config,
beanDesc, elementTypeDeserializer, elementDeserializer);
if (deser != null) {
return deser;
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl: Collection(-like) deserializers
/**********************************************************
*/
@Override
public JsonDeserializer<?> createCollectionDeserializer(DeserializationContext ctxt,
CollectionType type, BeanDescription beanDesc)
throws JsonMappingException
{
JavaType contentType = type.getContentType();
// Very first thing: is deserializer hard-coded for elements?
JsonDeserializer<Object> contentDeser = contentType
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>#161]: No default constructor for ArrayBlockingQueue...
if (type.getRawClass() == ArrayBlockingQueue.class) {
return new ArrayBlockingQueueDeserializer(type, contentDeser, contentTypeDeser, inst, null);
}
}
// 13-Dec-2010, tatu: Can use more optimal deserializer if content type is String, so:
if (contentType.getRawClass() == String.class) {
// no value type deserializer because Strings are one of natural/native types:
deser = new StringCollectionDeserializer(type, contentDeser, inst);
} else {
deser = new CollectionDeserializer(type, contentDeser, contentTypeDeser, inst);
}
}
}
// and then new with 2.2: ability to post-process it too (Issue#120)
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyCollectionDeserializer(config, type, beanDesc, deser);
}
}
return deser;
}
protected CollectionType _mapAbstractCollectionType(JavaType type, DeserializationConfig config)
{
Class<?> collectionClass = type.getRawClass();
collectionClass = _collectionFallbacks.get(collectionClass.getName());
if (collectionClass == null) {
return null;
}
return (CollectionType) config.constructSpecializedType(type, collectionClass);
}
protected JsonDeserializer<?> _findCustomCollectionDeserializer(CollectionType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findCollectionDeserializer(type, config, beanDesc,
elementTypeDeserializer, elementDeserializer);
if (deser != null) {
return deser;
}
}
return null;
}
// Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
@Override
public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
CollectionLikeType type, final BeanDescription beanDesc)
throws JsonMappingException
{
JavaType contentType = type.getContentType();
// Very first thing: is deserializer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> hard-coded for elements?
JsonDeserializer<Object> contentDeser = contentType.getValueHandler();
final DeserializationConfig config = ctxt.getConfig();
// Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
// but if not, may still be possible to find:
if (contentTypeDeser == null) {
contentTypeDeser = findTypeDeserializer(config, contentType);
}
JsonDeserializer<?> deser = _findCustomCollectionLikeDeserializer(type, config, beanDesc,
contentTypeDeser, contentDeser);
if (deser != null) {
// and then new with 2.2: ability to post-process it too (Issue#120)
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyCollectionLikeDeserializer(config, type, beanDesc, deser);
}
}
}
return deser;
}
protected JsonDeserializer<?> _findCustomCollectionLikeDeserializer(CollectionLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findCollectionLikeDeserializer(type, config, beanDesc,
elementTypeDeserializer, elementDeserializer);
if (deser != null) {
return deser;
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl: Map(-like) deserializers
/**********************************************************
*/
@Override
public JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
MapType type, BeanDescription beanDesc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
JavaType keyType = type.getKeyType();
JavaType contentType = type.getContentType();
// First: is there annotation-specified deserializer for values?
@SuppressWarnings("unchecked")
JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
// Ok: need a key deserializer (null indicates 'default' here)
KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler();
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>concrete Map type "+type);
}
deser = AbstractDeserializer.constructForNonPOJO(beanDesc);
}
}
if (deser == null) {
ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser);
md.setIgnorableProperties(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()));
deser = md;
}
}
}
// and then new with 2.2: ability to post-process it too (Issue#120)
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyMapDeserializer(config, type, beanDesc, deser);
}
}
return deser;
}
// Copied almost verbatim from "createMapDeserializer" -- should try to share more code
@Override
public JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
MapLikeType type, final BeanDescription beanDesc)
throws JsonMappingException
{
JavaType keyType = type.getKeyType();
JavaType contentType = type.getContentType();
final DeserializationConfig config = ctxt.getConfig();
// First: is there annotation-specified deserializer for values?
@SuppressWarnings("unchecked")
JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
// Ok: need a key deserializer (null indicates 'default' here)
KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler();
/* !!! 24-Jan-2012, tatu: NOTE: impls MUST use resolve() to find key deserializer!
if (keyDes == null) {
keyDes = p.findKeyDeserializer(config, keyType, property);
}
*/
// Then optional type info (1.5); either attached to type, or resolve separately:
TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
// but if not, may still be possible to find:
if (contentTypeDeser == null) {
contentTypeDeser = findTypeDeserializer(config, contentType);
}
JsonDeserializer<?> deser = _findCustomMapLikeDeserializer(type, config,
beanDesc, key
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Des, contentTypeDeser, contentDeser);
if (deser != null) {
// and then new with 2.2: ability to post-process it too (Issue#120)
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyMapLikeDeserializer(config, type, beanDesc, deser);
}
}
}
return deser;
}
protected JsonDeserializer<?> _findCustomMapDeserializer(MapType type,
DeserializationConfig config, BeanDescription beanDesc,
KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findMapDeserializer(type, config, beanDesc,
keyDeserializer, elementTypeDeserializer, elementDeserializer);
if (deser != null) {
return deser;
}
}
return null;
}
protected JsonDeserializer<?> _findCustomMapLikeDeserializer(MapLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findMapLikeDeserializer(type, config, beanDesc,
keyDeserializer, elementTypeDeserializer, elementDeserializer);
if (deser != null) {
return deser;
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl: Enum deserializers
/**********************************************************
*/
/**
* Factory method for constructing serializers of {@link Enum} types.
*/
@Override
public JsonDeserializer<?> createEnumDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
final Class<?> enumClass = type.getRawClass();
// 23-Nov-2010, tatu: Custom deserializer?
JsonDeserializer<?> deser = _findCustomEnumDeserializer(enumClass, config, beanDesc);
if (deser == null) {
// [JACKSON-193] May have @JsonCreator
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> for static factory method:
for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
if (ctxt.getAnnotationIntrospector().hasCreatorAnnotation(factory)) {
int argCount = factory.getParameterCount();
if (argCount == 1) {
Class<?> returnType = factory.getRawReturnType();
// usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
if (returnType.isAssignableFrom(enumClass)) {
deser = EnumDeserializer.deserializerForCreator(config, enumClass, factory);
break;
}
}
throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type "
+enumClass.getName()+")");
}
}
// [JACKSON-749] Also, need to consider @JsonValue, if one found
if (deser == null) {
deser = new EnumDeserializer(constructEnumResolver(enumClass, config, beanDesc.findJsonValueMethod()));
}
}
// and then new with 2.2: ability to post-process it too (Issue#120)
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyEnumDeserializer(config, type, beanDesc, deser);
}
}
return deser;
}
protected JsonDeserializer<?> _findCustomEnumDeserializer(Class<?> type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findEnumDeserializer(type, config, beanDesc);
if (deser != null) {
return deser;
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl: Tree deserializers
/**********************************************************
*/
@Override
public JsonDeserializer<?> createTreeDeserializer(DeserializationConfig config,
JavaType nodeType, BeanDescription beanDesc)
throws JsonMappingException
{
@SuppressWarnings("unchecked")
Class<? extends JsonNode> nodeClass = (Class<? extends JsonNode>) nodeType.getRawClass();
// 23-Nov-2010, tatu: Custom deserializer?
JsonDeserializer<?> custom = _findCustomTreeNodeDeserializer(nodeClass,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> config,
beanDesc);
if (custom != null) {
return custom;
}
return JsonNodeDeserializer.getDeserializer(nodeClass);
}
protected JsonDeserializer<?> _findCustomTreeNodeDeserializer(Class<? extends JsonNode> type,
DeserializationConfig config, BeanDescription beanDesc)
throws JsonMappingException
{
for (Deserializers d : _factoryConfig.deserializers()) {
JsonDeserializer<?> deser = d.findTreeNodeDeserializer(type, config, beanDesc);
if (deser != null) {
return deser;
}
}
return null;
}
/*
/**********************************************************
/* JsonDeserializerFactory impl (partial): type deserializers
/**********************************************************
*/
@Override
public TypeDeserializer findTypeDeserializer(DeserializationConfig config,
JavaType baseType)
throws JsonMappingException
{
BeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass());
AnnotatedClass ac = bean.getClassInfo();
AnnotationIntrospector ai = config.getAnnotationIntrospector();
TypeResolverBuilder<?> b = ai.findTypeResolver(config, ac, baseType);
/* Ok: if there is no explicit type info handler, we may want to
* use a default. If so, config object knows what to use.
*/
Collection<NamedType> subtypes = null;
if (b == null) {
b = config.getDefaultTyper(baseType);
if (b == null) {
return null;
}
} else {
subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai);
}
// [JACKSON-505]: May need to figure out default implementation, if none found yet
// (note: check for abstract type is not 100% mandatory, more of an optimization)
if ((b.getDefaultImpl() == null) && baseType.isAbstract()) {
JavaType defaultType = mapAbstractType(config, baseType);
if (defaultType != null && defaultType.getRawClass() != baseType.getRawClass()) {
b = b.defaultImpl(defaultType.getRawClass());
}
}
return b.buildTypeDeserializer(config, baseType, subtypes);
}
/*
/**********************************************************
/* JsonDeserializerFactory impl (partial): key deserializers
/********************************************************
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>**
*/
@Override
public KeyDeserializer createKeyDeserializer(DeserializationContext ctxt,
JavaType type)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
KeyDeserializer deser = null;
if (_factoryConfig.hasKeyDeserializers()) {
BeanDescription beanDesc = config.introspectClassAnnotations(type.getRawClass());
for (KeyDeserializers d : _factoryConfig.keyDeserializers()) {
deser = d.findKeyDeserializer(type, config, beanDesc);
if (deser != null) {
break;
}
}
}
// the only non-standard thing is this:
if (deser == null) {
if (type.isEnumType()) {
return _createEnumKeyDeserializer(ctxt, type);
}
deser = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type);
}
// and then new with 2.2: ability to post-process it too (Issue#120)
if (deser != null) {
if (_factoryConfig.hasDeserializerModifiers()) {
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
deser = mod.modifyKeyDeserializer(config, type, deser);
}
}
}
return deser;
}
private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt,
JavaType type)
throws JsonMappingException
{
final DeserializationConfig config = ctxt.getConfig();
BeanDescription beanDesc = config.introspect(type);
JsonDeserializer<?> des = findDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo());
if (des != null) {
return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, des);
}
Class<?> enumClass = type.getRawClass();
// 23-Nov-2010, tatu: Custom deserializer?
JsonDeserializer<?> custom = _findCustomEnumDeserializer(enumClass, config, beanDesc);
if (custom != null) {
return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, custom);
}
EnumResolver<?> enumRes = constructEnumResolver(enumClass, config, beanDesc.findJsonValueMethod());
// [JACKSON-193] May have @JsonCreator for static factory method:
for (AnnotatedMethod factory
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> : beanDesc.getFactoryMethods()) {
if (config.getAnnotationIntrospector().hasCreatorAnnotation(factory)) {
int argCount = factory.getParameterCount();
if (argCount == 1) {
Class<?> returnType = factory.getRawReturnType();
// usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
if (returnType.isAssignableFrom(enumClass)) {
// note: mostly copied from 'EnumDeserializer.deserializerForCreator(...)'
if (factory.getGenericParameterType(0) != String.class) {
throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory+") not suitable, must be java.lang.String");
}
if (config.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(factory.getMember());
}
return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory);
}
}
throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type "
+enumClass.getName()+")");
}
}
// [JACKSON-749] Also, need to consider @JsonValue, if one found
return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes);
}
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
/**
* Method called to create a type information deserializer for values of
* given non-container property, if one is needed.
* If not needed (no polymorphic handling configured for property), should return null.
*<p>
* Note that this method is only called for non-container bean properties,
* and not for values in container types or root values (or container properties)
*
* @param baseType Declared base type of the value to deserializer (actual
* deserializer type will be this type or its subtype)
*
* @return Type deserializer to use for given base type, if one is needed; null if not.
*/
public TypeDeserializer findPropertyTypeDeserializer(DeserializationConfig config,
JavaType baseType, AnnotatedMember annotated)
throws JsonMappingException
{
AnnotationIntrospector ai = config.getAnnotationIntrospector();
TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(config, annotated, baseType);
// Defaulting: if no annotations
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> on member, check value class
if (b == null) {
return findTypeDeserializer(config, baseType);
}
// but if annotations found, may need to resolve subtypes:
Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(
annotated, config, ai, baseType);
return b.buildTypeDeserializer(config, baseType, subtypes);
}
/**
* Method called to find and create a type information deserializer for values of
* given container (list, array, map) property, if one is needed.
* If not needed (no polymorphic handling configured for property), should return null.
*<p>
* Note that this method is only called for container bean properties,
* and not for values in container types or root values (or non-container properties)
*
* @param containerType Type of property; must be a container type
* @param propertyEntity Field or method that contains container property
*/
public TypeDeserializer findPropertyContentTypeDeserializer(DeserializationConfig config,
JavaType containerType, AnnotatedMember propertyEntity)
throws JsonMappingException
{
AnnotationIntrospector ai = config.getAnnotationIntrospector();
TypeResolverBuilder<?> b = ai.findPropertyContentTypeResolver(config, propertyEntity, containerType);
JavaType contentType = containerType.getContentType();
// Defaulting: if no annotations on member, check class
if (b == null) {
return findTypeDeserializer(config, contentType);
}
// but if annotations found, may need to resolve subtypes:
Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(
propertyEntity, config, ai, contentType);
return b.buildTypeDeserializer(config, contentType, subtypes);
}
/**
* Helper method called to find one of default serializers for "well-known"
* platform types: JDK-provided types, and small number of public Jackson
* API types.
*
* @since 2.2
*/
public JsonDeserializer<?> findDefaultDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException
{
Class<?> rawType = type.getRawClass();
// Object ("untyped"), String equivalents:
if (rawType == CLASS_OBJECT) {
return new Untyped
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>ObjectDeserializer();
}
if (rawType == CLASS_STRING || rawType == CLASS_CHAR_BUFFER) {
return StringDeserializer.instance;
}
if (rawType == CLASS_ITERABLE) {
// [Issue#199]: Can and should 'upgrade' to a Collection type:
TypeFactory tf = ctxt.getTypeFactory();
JavaType elemType = (type.containedTypeCount() > 0) ? type.containedType(0) : TypeFactory.unknownType();
CollectionType ct = tf.constructCollectionType(Collection.class, elemType);
// Should we re-introspect beanDesc? For now let's not...
return createCollectionDeserializer(ctxt, ct, beanDesc);
}
String clsName = rawType.getName();
if (rawType.isPrimitive() || clsName.startsWith("java.")) {
// Primitives/wrappers, other Numbers:
JsonDeserializer<?> deser = NumberDeserializers.find(rawType, clsName);
if (deser == null) {
deser = DateDeserializers.find(rawType, clsName);
}
if (deser != null) {
return deser;
}
}
// and a few Jackson types as well:
if (rawType == TokenBuffer.class) {
return new TokenBufferDeserializer();
}
return JdkDeserializers.find(rawType, clsName);
}
/*
/**********************************************************
/* Helper methods, value/content/key type introspection
/**********************************************************
*/
/**
* Helper method called to check if a class or method
* has annotation that tells which class to use for deserialization.
* Returns null if no such annotation found.
*/
protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationContext ctxt,
Annotated ann)
throws JsonMappingException
{
Object deserDef = ctxt.getAnnotationIntrospector().findDeserializer(ann);
if (deserDef == null) {
return null;
}
return ctxt.deserializerInstance(ann, deserDef);
}
/**
* Method called to see if given method has annotations that indicate
* a more specific type than what the argument specifies.
* If annotations are present, they must specify compatible Class;
* instance of which can be assigned using the method. This means
* that the Class has to be
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> raw class of type, or its sub-class
* (or, implementing class if original Class instance is an interface).
*
* @param a Method or field that the type is associated with
* @param type Type of field, or the setter argument
*
* @return Original type if no annotations are present; or a more
* specific type derived from it if type annotation(s) was found
*
* @throws JsonMappingException if invalid annotation is found
*/
@SuppressWarnings({ "unchecked" })
protected <T extends JavaType> T modifyTypeByAnnotation(DeserializationContext ctxt,
Annotated a, T type)
throws JsonMappingException
{
// first: let's check class for the instance itself:
AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
Class<?> subclass = intr.findDeserializationType(a, type);
if (subclass != null) {
try {
type = (T) type.narrowBy(subclass);
} catch (IllegalArgumentException iae) {
throw new JsonMappingException("Failed to narrow type "+type+" with concrete-type annotation (value "+subclass.getName()+"), method '"+a.getName()+"': "+iae.getMessage(), null, iae);
}
}
// then key class
if (type.isContainerType()) {
Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType());
if (keyClass != null) {
// illegal to use on non-Maps
if (!(type instanceof MapLikeType)) {
throw new JsonMappingException("Illegal key-type annotation: type "+type+" is not a Map(-like) type");
}
try {
type = (T) ((MapLikeType) type).narrowKey(keyClass);
} catch (IllegalArgumentException iae) {
throw new JsonMappingException("Failed to narrow key type "+type+" with key-type annotation ("+keyClass.getName()+"): "+iae.getMessage(), null, iae);
}
}
JavaType keyType = type.getKeyType();
/* 21-Mar-2011, tatu: ... and associated deserializer too (unless already assigned)
* (not 100% why or how, but this does seem to get called more than once, which
* is not good: for now, let's
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> just avoid errors)
*/
if (keyType != null && keyType.getValueHandler() == null) {
Object kdDef = intr.findKeyDeserializer(a);
KeyDeserializer kd = ctxt.keyDeserializerInstance(a, kdDef);
if (kd != null) {
type = (T) ((MapLikeType) type).withKeyValueHandler(kd);
keyType = type.getKeyType(); // just in case it's used below
}
}
// and finally content class; only applicable to structured types
Class<?> cc = intr.findDeserializationContentType(a, type.getContentType());
if (cc != null) {
try {
type = (T) type.narrowContentsBy(cc);
} catch (IllegalArgumentException iae) {
throw new JsonMappingException("Failed to narrow content type "+type+" with content-type annotation ("+cc.getName()+"): "+iae.getMessage(), null, iae);
}
}
// ... as well as deserializer for contents:
JavaType contentType = type.getContentType();
if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception)
Object cdDef = intr.findContentDeserializer(a);
JsonDeserializer<?> cd = ctxt.deserializerInstance(a, cdDef);
if (cd != null) {
type = (T) type.withContentValueHandler(cd);
}
}
}
return type;
}
/**
* Helper method used to resolve method return types and field
* types. The main trick here is that the containing bean may
* have type variable binding information (when deserializing
* using generic type passed as type reference), which is
* needed in some cases.
*/
protected JavaType resolveType(DeserializationContext ctxt,
BeanDescription beanDesc, JavaType type, AnnotatedMember member)
throws JsonMappingException
{
// [JACKSON-154]: Also need to handle keyUsing, contentUsing
if (type.isContainerType()) {
AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
JavaType keyType = type.getKeyType();
if (keyType != null) {
Object kdDef = intr.findKeyDeserializer(member);
KeyDeserializer kd = ctxt.keyDeserializerInstance(member, k
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> /**
* Convenience method for creating a new factory instance with additional deserializer
* provider.
*/
public abstract DeserializerFactory withAdditionalDeserializers(Deserializers additional);
/**
* Convenience method for creating a new factory instance with additional
* {@link KeyDeserializers}.
*/
public abstract DeserializerFactory withAdditionalKeyDeserializers(KeyDeserializers additional);
/**
* Convenience method for creating a new factory instance with additional
* {@link BeanDeserializerModifier}.
*/
public abstract DeserializerFactory withDeserializerModifier(BeanDeserializerModifier modifier);
/**
* Convenience method for creating a new factory instance with additional
* {@link AbstractTypeResolver}.
*/
public abstract DeserializerFactory withAbstractTypeResolver(AbstractTypeResolver resolver);
/**
* Convenience method for creating a new factory instance with additional
* {@link ValueInstantiators}.
*/
public abstract DeserializerFactory withValueInstantiators(ValueInstantiators instantiators);
/*
/**********************************************************
/* Basic DeserializerFactory API:
/**********************************************************
*/
/**
* Method that can be called to try to resolve an abstract type
* (interface, abstract class) into a concrete type, or at least
* something "more concrete" (abstract class instead of interface).
* Will either return passed type, or a more specific type.
*/
public abstract JavaType mapAbstractType(DeserializationConfig config, JavaType type)
throws JsonMappingException;
/**
* Method that is to find all creators (constructors, factory methods)
* for the bean type to deserialize.
*/
public abstract ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
BeanDescription beanDesc)
throws JsonMappingException;
/**
* Method called to create (or, for completely immutable deserializers,
* reuse) a deserializer that can convert JSON content into values of
* specified Java "bean" (POJO) type.
* At this point it is known that the type is not otherwise recognized
* as one of structured types (array, Collection, Map) or a well-known
* JDK type (enum, primitives/wrappers, String); this method only
* gets called if other options are exhausted. This also means that
* this method can be overridden to add support for custom types.
*
* @param type Type to be deserialized
*/
public abstract JsonDeserializer<Object> createBeanDeserializer(Deserialization
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Context ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException;
/**
* Method called to create a deserializer that will use specified Builder
* class for building value instances.
*
* @since 2.0
*/
public abstract JsonDeserializer<Object> createBuilderBasedDeserializer(
DeserializationContext ctxt, JavaType type, BeanDescription beanDesc,
Class<?> builderClass)
throws JsonMappingException;
/**
* Method called to create (or, for completely immutable deserializers,
* reuse) a deserializer that can convert JSON content into values of
* specified Java type.
*
* @param type Type to be deserialized
*/
public abstract JsonDeserializer<?> createArrayDeserializer(DeserializationContext ctxt,
ArrayType type, BeanDescription beanDesc)
throws JsonMappingException;
public abstract JsonDeserializer<?> createCollectionDeserializer(DeserializationContext ctxt,
CollectionType type, BeanDescription beanDesc)
throws JsonMappingException;
public abstract JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
CollectionLikeType type, BeanDescription beanDesc)
throws JsonMappingException;
public abstract JsonDeserializer<?> createEnumDeserializer(DeserializationContext ctxt,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException;
public abstract JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
MapType type, BeanDescription beanDesc)
throws JsonMappingException;
public abstract JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
MapLikeType type, BeanDescription beanDesc)
throws JsonMappingException;
/**
* Method called to create and return a deserializer that can construct
* JsonNode(s) from JSON content.
*/
public abstract JsonDeserializer<?> createTreeDeserializer(DeserializationConfig config,
JavaType type, BeanDescription beanDesc)
throws JsonMappingException;
/**
* Method called to find if factory knows how to create a key deserializer
* for specified type; currently this means checking if a module has registered
* possible deserializers.
*
* @return Key deserializer to use for specified type, if one found; null if not
* (and default key deserializer should be used)
*/
public abstract KeyDeserializer createKeyDeserializer(DeserializationContext ctxt,
JavaType type)
throws JsonMappingException;
/**
* Method called to find and create a type information deserializer for given base type,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
* if one is needed. If not needed (no polymorphic handling configured for type),
* should return null.
*<p>
* Note that this method is usually only directly called for values of container (Collection,
* array, Map) types and root values, but not for bean property values.
*
* @param baseType Declared base type of the value to deserializer (actual
* deserializer type will be this type or its subtype)
*
* @return Type deserializer to use for given base type, if one is needed; null if not.
*/
public abstract TypeDeserializer findTypeDeserializer(DeserializationConfig config,
JavaType baseType)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.ser.std;
import java.io.IOException;
import java.lang.reflect.Type;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
/**
* This is the special serializer for regular {@link java.lang.String}s.
*<p>
* Since this is one of "native" types, no type information is ever
* included on serialization (unlike for most scalar types as of 1.5)
*/
@JacksonStdImpl
public final class StringSerializer
extends NonTypedScalarSerializerBase<String>
{
public StringSerializer() { super(String.class); }
/**
* For Strings, both null and Empty String qualify for emptiness.
*/
@Override
public boolean isEmpty(String value) {
return (value == null) || (value.length() == 0);
}
@Override
public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return createSchemaNode("string", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
if (visitor != null) visitor.expectStringFormat(typeHint);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> _elementTypeDeserializer)) {
return this;
}
return new ObjectArrayDeserializer(_arrayType,
(JsonDeserializer<Object>) elemDeser, elemTypeDeser);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonDeserializer<?> deser = _elementDeserializer;
// #125: May have a content converter
deser = findConvertingContentDeserializer(ctxt, property, deser);
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(_arrayType.getContentType(), property);
} else { // if directly assigned, probably not yet contextual, so:
deser = ctxt.handleSecondaryContextualization(deser, property);
}
TypeDeserializer elemTypeDeser = _elementTypeDeserializer;
if (elemTypeDeser != null) {
elemTypeDeser = elemTypeDeser.forProperty(property);
}
return withDeserializer(elemTypeDeser, deser);
}
/*
/**********************************************************
/* ContainerDeserializerBase API
/**********************************************************
*/
@Override
public JavaType getContentType() {
return _arrayType.getContentType();
}
@Override
public JsonDeserializer<Object> getContentDeserializer() {
return _elementDeserializer;
}
/*
/**********************************************************
/* JsonDeserializer API
/**********************************************************
*/
@Override
public Object[] deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
final TypeDeserializer typeDeser = _elementTypeDeserializer;
try {
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Note: must handle null explicitly here; value deserializers won't
Object value;
if (t == JsonToken.VALUE_NULL) {
value = _elementDeserializer.getNullValue();
} else if (typeDeser == null) {
value = _elementDeserializer.deserialize(jp, ctxt);
} else {
value = _element
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Deserializer.deserializeWithType(jp, ctxt, typeDeser);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
} catch (Exception e) {
// note: pass Object.class, not Object[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, Object.class, ix);
}
Object[] result;
if (_untyped) {
result = buffer.completeAndClearBuffer(chunk, ix);
} else {
result = buffer.completeAndClearBuffer(chunk, ix, _elementClass);
}
ctxt.returnObjectBuffer(buffer);
return result;
}
@Override
public Object[] deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
/* Should there be separate handling for base64 stuff?
* for now this should be enough:
*/
return (Object[]) typeDeserializer.deserializeTypedFromArray(jp, ctxt);
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected Byte[] deserializeFromBase64(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// First same as what PrimitiveArrayDeserializers.ByteDeser does:
byte[] b = jp.getBinaryValue(ctxt.getBase64Variant());
// But then need to convert to wrappers
Byte[] result = new Byte[b.length];
for (int i = 0, len = b.length; i < len; ++i) {
result[i] = Byte.valueOf(b[i]);
}
return result;
}
private final Object[] handleNonArray(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// [JACKSON-620] Empty String can become null...
if ((jp.getCurrentToken() == JsonToken.VALUE_STRING)
&& ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
String str = jp.getText();
if (str.length() == 0) {
return null;
}
}
// Can we do implicit coercion
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
}
it.next();
return !it.hasNext();
}
/*
/**********************************************************
/* Actual serialization
/**********************************************************
*/
@Override
public void serializeContents(Collection<?> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
if (_elementSerializer != null) {
serializeContentsUsing(value, jgen, provider, _elementSerializer);
return;
}
Iterator<?> it = value.iterator();
if (!it.hasNext()) {
return;
}
PropertySerializerMap serializers = _dynamicSerializers;
final TypeSerializer typeSer = _valueTypeSerializer;
int i = 0;
try {
do {
Object elem = it.next();
if (elem == null) {
provider.defaultSerializeNull(jgen);
} else {
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = serializers.serializerFor(cc);
if (serializer == null) {
// To fix [JACKSON-508]
if (_elementType.hasGenericTypes()) {
serializer = _findAndAddDynamic(serializers,
provider.constructSpecializedType(_elementType, cc), provider);
} else {
serializer = _findAndAddDynamic(serializers, cc, provider);
}
serializers = _dynamicSerializers;
}
if (typeSer == null) {
serializer.serialize(elem, jgen, provider);
} else {
serializer.serializeWithType(elem, jgen, provider, typeSer);
}
}
++i;
} while (it.hasNext());
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, i);
}
}
public void serializeContentsUsing(Collection<?> value, JsonGenerator jgen, SerializerProvider provider,
JsonSerializer<Object> ser)
throws IOException, JsonGenerationException
{
Iterator<?> it = value.iterator();
if (it.hasNext()) {
TypeSerializer typeSer = _valueTypeSerializer;
int i = 0;
do {
Object elem = it.next();
try {
if (elem == null) {
provider.defaultSerializeNull(jgen);
} else {
if (typeSer == null) {
ser.serialize(elem,
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> jgen, provider);
} else {
ser.serializeWithType(elem, jgen, provider, typeSer);
}
}
++i;
} catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, i);
}
} while (it.hasNext());
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser;
import com.fasterxml.jackson.databind.*;
/**
* Add-on interface that {@link JsonDeserializer}s can implement to get a callback
* that can be used to create contextual (context-dependent) instances of
* deserializer to use for handling properties of supported type.
* This can be useful
* for deserializers that can be configured by annotations, or should otherwise
* have differing behavior depending on what kind of property is being deserialized.
*<p>
* Note that in cases where deserializer needs both contextualization and
* resolution -- that is, implements both this interface and {@link ResolvableDeserializer}
* -- resolution via {@link ResolvableDeserializer} occurs first, and contextual
* resolution (via this interface) later on.
*/
public interface ContextualDeserializer
{
/**
* Method called to see if a different (or differently configured) deserializer
* is needed to deserialize values of specified property.
* Note that instance that this method is called on is typically shared one and
* as a result method should <b>NOT</b> modify this instance but rather construct
* and return a new instance. This instance should only be returned as-is, in case
* it is already suitable for use.
*
* @param ctxt Deserialization context to access configuration, additional
* deserializers that may be needed by this deserializer
* @param property Method, field or constructor parameter that represents the property
* (and is used to assign deserialized value).
* Should be available; but there may be cases where caller can not provide it and
* null is passed instead (in which case impls usually pass 'this' deserializer as is)
*
* @return Deserializer to use for deserializing values of specified property;
* may be this instance or a new instance.
*
* @throws JsonMappingException
*/
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser.impl;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
/**
* Special bogus "serializer" that will throw
* {@link JsonMappingException} if an attempt is made to deserialize
* a value. This is used as placeholder to avoid NPEs for uninitialized
* structured serializers or handlers.
*/
public class FailingDeserializer extends StdDeserializer<Object>
{
private static final long serialVersionUID = 1L;
protected final String _message;
public FailingDeserializer(String m) {
super(Object.class);
_message = m;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws JsonMappingException{
throw ctxt.mappingException(_message);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/*
/**********************************************************
/* Concrete deserialization methods
/**********************************************************
*/
/**
* Streamlined version that is only used when no "special"
* features are enabled.
*/
private final Object vanillaDeserialize(JsonParser jp,
DeserializationContext ctxt, JsonToken t)
throws IOException, JsonProcessingException
{
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
} else {
handleUnknownVanilla(jp, ctxt, bean, propName);
}
}
return bean;
}
/**
* General version used when handling needs more advanced
* features.
*/
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_nonStandardCreation) {
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(jp, ctxt);
}
if (_externalTypeIdHandler != null) {
return deserializeWithExternalTypeId(jp, ctxt);
}
Object bean = deserializeFromObjectUsingNonDefault(jp, ctxt);
if (_injectables != null) {
injectValues(ctxt, bean);
}
/* 27-May-2014, tatu: I don't think view processing would work
* at this point, so commenting it out; but leaving in place
* just in case I forgot something fundamental...
*/
/*
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(jp, ctxt
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, bean, view);
}
}
*/
return bean;
}
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (jp.canReadObjectId()) {
Object id = jp.getObjectId();
if (id != null) {
_handleTypedObjectId(jp, ctxt, bean, id);
}
}
if (_injectables != null) {
injectValues(ctxt, bean);
}
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(jp, ctxt, bean, view);
}
}
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/**
* Method called to deserialize bean using "property-based creator":
* this means that a non-default constructor or factory method is
* called, and then possibly other setters. The trick is that
* values for creator method need to be buffered, first; and
* due to non-guaranteed ordering possibly some other properties
* as well.
*/
@Override
@SuppressWarnings("resource")
protected Object _deserializeUsingPropertyBased(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
// 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
TokenBuffer unknown = null;
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
bean = null; // never gets here
}
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(jp, ctxt, bean, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
bean = handleUnknownProperties(ctxt, bean, unknown);
}
// or just clean?
return deserialize(jp, ctxt, bean);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
// As per [JACKSON-313], things marked as ignorable should not be
// passed to any setter
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, handledType(), propName);
continue;
}
// "any property"?
if (_anySetter != null) {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
continue;
}
// Ok then, let's collect the whole field; name and value
if (unknown == null) {
unknown = new TokenBuffer(jp);
}
unknown.writeFieldName(propName);
unknown.copyCurrentStructure(jp);
}
// We hit END_OBJECT, so:
Object bean;
try {
bean = creator.
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
bean = null; // never gets here
}
if (unknown != null) {
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(null, ctxt, bean, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, bean, unknown);
}
return bean;
}
/*
/**********************************************************
/* Deserializing when we have to consider an active View
/**********************************************************
*/
protected final Object deserializeWithView(JsonParser jp, DeserializationContext ctxt,
Object bean, Class<?> activeView)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
if (!prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
handleUnknownVanilla(jp, ctxt, bean, propName);
}
return bean;
}
/*
/**********************************************************
/* Handling for cases where we have "unwrapped" values
/**********************************************************
*/
/**
* Method called when there are declared "unwrapped" properties
* which need special handling
*/
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
}
if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithUnwrapped(jp, ctxt);
}
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
if (_
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>injectables != null) {
injectValues(ctxt, bean);
}
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser jp, DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
SettableBeanProperty prop = _beanProperties.find(prop
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Name);
jp.nextToken();
if (prop != null) { // normal case
if (activeView != null && !prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but... others should be passed to unwrapped property deserializers
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// how about any setter? We'll get copies but...
if (_anySetter != null) {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
}
}
tokens.writeEndObject();
_unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
return bean;
}
@SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; //
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> never gets here
}
// if so, need to copy all remaining tokens into buffer
while (t == JsonToken.FIELD_NAME) {
jp.nextToken(); // to skip name
tokens.copyCurrentStructure(jp);
t = jp.nextToken();
}
tokens.writeEndObject();
if (bean.getClass() != _beanType.getRawClass()) {
// !!! 08-Jul-2011, tatu: Could probably support; but for now
// it's too complicated, so bail out
tokens.close();
throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
}
return _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, handledType(), propName);
continue;
}
tokens.writeFieldName(propName);
tokens.copyCurrentStructure(jp);
// "any property"?
if (_anySetter != null) {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
}
}
// We hit END_OBJECT, so:
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
return _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens);
}
/*
/**********************************************************
/* Handling for cases where we have property/-ies with
/* external type id
/**********************************************************
*/
protected Object deserializeWithExternalTypeId(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithExternalTypeId(jp, ctxt);
}
return deserializeWithExternalTypeId(jp, ctxt, _valueInstantiator.createUsingDefault(ctxt));
}
protected Object deserializeWithExternalTypeId(JsonParser jp, DeserializationContext ctxt,
Object bean)
throws IOException, JsonProcessingException
{
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
final ExternalTypeHandler ext = _externalTypeIdHandler.start();
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) { // normal case
// [JACKSON-831]: may have property AND be used as external type id:
if (jp.getCurrentToken().isScalarValue()) {
ext.handleTypePropertyValue(jp, ctxt, propName, bean);
}
if (activeView != null && !prop.visibleInView(activeView)) {
jp.skipChildren();
continue;
}
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// ignorable things should be ignored
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, bean, propName);
continue;
}
// but others are likely to be part of external type id thingy...
if (ext.handlePropertyValue(jp, ctxt, propName, bean)) {
continue;
}
// if not, the usual fallback handling:
if (_anySetter != null) {
try {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
continue;
}
// Unknown: let's call handler method
handleUnknownProperty(jp, ctxt, bean, propName);
}
// and when we get this far, let's try finalizing the deal:
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
return ext.complete(jp, ctxt, bean);
}
@SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final ExternalTypeHandler ext = _externalTypeIdHandler.start();
final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt, _objectIdReader);
TokenBuffer tokens = new TokenBuffer(jp);
tokens.writeStartObject();
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
if (creatorProp != null) {
// first: let's check to see if this might be part of value with external type id:
if (ext.handlePropertyValue(jp, ctxt, propName, buffer)) {
;
} else {
// Last creator property to set?
Object value = creatorProp.deserialize(jp, ctxt);
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean;
try {
bean = creator.build(ctxt, buffer);
} catch (Exception e) {
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
continue; // never gets here
}
// if so, need to copy all remaining tokens into buffer
while (t == JsonToken.FIELD_NAME) {
jp.nextToken(); // to skip name
tokens.copyCurrentStructure(jp);
t = jp.nextToken();
}
if (bean.getClass() != _beanType.getRawClass()) {
// !!! 08-Jul-2011, tatu: Could probably support; but for now
// it's too complicated, so bail out
throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values");
}
return ext.complete(jp, ctxt, bean);
}
}
continue;
}
// Object Id property?
if (buffer.readIdProperty(
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>propName)) {
continue;
}
// regular property? needs buffering
SettableBeanProperty prop = _beanProperties.find(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
// external type id (or property that depends on it)?
if (ext.handlePropertyValue(jp, ctxt, propName, null)) {
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
handleIgnoredProperty(jp, ctxt, handledType(), propName);
continue;
}
// "any property"?
if (_anySetter != null) {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
}
}
// We hit END_OBJECT; resolve the pieces:
try {
return ext.complete(jp, ctxt, buffer, creator);
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
return null; // never gets here
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
/**
* Exception thrown during deserialization when there are object id that can't
* be resolved.
*
* @author pgelinas
*/
public final class UnresolvedForwardReference extends JsonMappingException {
private static final long serialVersionUID = 1L;
private ReadableObjectId _roid;
private List<UnresolvedId> _unresolvedIds;
public UnresolvedForwardReference(String msg, JsonLocation loc, ReadableObjectId roid)
{
super(msg, loc);
_roid = roid;
}
public UnresolvedForwardReference(String msg)
{
super(msg);
_unresolvedIds = new ArrayList<UnresolvedId>();
}
// ******************************
// ****** Accessor methods ******
// ******************************
public ReadableObjectId getRoid() {
return _roid;
}
public Object getUnresolvedId() {
return _roid.getKey().key;
}
public void addUnresolvedId(Object id, Class<?> type, JsonLocation where) {
_unresolvedIds.add(new UnresolvedId(id, type, where));
}
public List<UnresolvedId> getUnresolvedIds(){
return _unresolvedIds;
}
@Override
public String getMessage()
{
String msg = super.getMessage();
if (_unresolvedIds == null) {
return msg;
}
StringBuilder sb = new StringBuilder(msg);
Iterator<UnresolvedId> iterator = _unresolvedIds.iterator();
while (iterator.hasNext()) {
UnresolvedId unresolvedId = iterator.next();
sb.append(unresolvedId.toString());
if (iterator.hasNext()) {
sb.append(", ");
}
}
sb.append('.');
return sb.toString();
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.jsonschema;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.lang.reflect.Type;
/**
* Marker interface for schema-aware serializers.
*/
public interface SchemaAware
{
/**
* Get the representation of the schema to which this serializer will conform.
*
* @param provider The serializer provider.
* @param typeHint A hint about the type.
* @return <a href="http://json-schema.org/">Json-schema</a> for this serializer.
*/
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException;
/**
* Get the representation of the schema to which this serializer will conform.
*
* @param provider The serializer provider.
* @param isOptional Is the type optional
* @param typeHint A hint about the type.
* @return <a href="http://json-schema.org/">Json-schema</a> for this serializer.
*/
public JsonNode getSchema(SerializerProvider provider, Type typeHint, boolean isOptional)
throws JsonMappingException;
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
serialize(value, jgen, provider);
typeSer.writeTypeSuffixForScalar(value, jgen);
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
{
/* 01-Jan-2010, tatu: Not 100% sure what we should say here:
* type is basically not known. This seems closest
* approximation
*/
return createSchemaNode("any", true);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
/* 01-Jan-2010, tatu: Not 100% sure what we should say here:
* type is basically not known. This seems closest
* approximation
*/
visitor.expectAnyFormat(typeHint);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> int getParameterCount() {
return _constructor.getParameterTypes().length;
}
@Override
public Class<?> getRawParameterType(int index)
{
Class<?>[] types = _constructor.getParameterTypes();
return (index >= types.length) ? null : types[index];
}
@Override
public Type getGenericParameterType(int index)
{
Type[] types = _constructor.getGenericParameterTypes();
return (index >= types.length) ? null : types[index];
}
@Override
public final Object call() throws Exception {
return _constructor.newInstance();
}
@Override
public final Object call(Object[] args) throws Exception {
return _constructor.newInstance(args);
}
@Override
public final Object call1(Object arg) throws Exception {
return _constructor.newInstance(arg);
}
/*
/**********************************************************
/* AnnotatedMember impl
/**********************************************************
*/
@Override
public Class<?> getDeclaringClass() { return _constructor.getDeclaringClass(); }
@Override
public Member getMember() { return _constructor; }
@Override
public void setValue(Object pojo, Object value)
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Cannot call setValue() on constructor of "
+getDeclaringClass().getName());
}
@Override
public Object getValue(Object pojo)
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Cannot call getValue() on constructor of "
+getDeclaringClass().getName());
}
/*
/**********************************************************
/* Extended API, specific annotations
/**********************************************************
*/
@Override
public String toString() {
return "[constructor for "+getName()+", annotations: "+_annotations+"]";
}
/*
/**********************************************************
/* JDK serialization handling
/**********************************************************
*/
Object writeReplace() {
return new AnnotatedConstructor(new Serialization(_constructor));
}
Object readResolve() {
Class<?> clazz = _serialization.clazz;
try {
Constructor<?> ctor = clazz.getDeclaredConstructor(_serialization.args);
// 06-Oct-2012, tatu: Has "lost" its security override, must force back
if (!ctor.isAccessible()) {
ClassUtil.checkAndFixAccess(ctor);
}
return new AnnotatedConstructor(ctor, null, null);
} catch (
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Exception e) {
throw new IllegalArgumentException("Could not find constructor with "
+_serialization.args.length+" args from Class '"+clazz.getName());
}
}
/**
* Helper class that is used as the workaround to persist
* Field references. It basically just stores declaring class
* and field name.
*/
private final static class Serialization
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected Class<?> clazz;
protected Class<?>[] args;
public Serialization(Constructor<?> ctor) {
clazz = ctor.getDeclaringClass();
args = ctor.getParameterTypes();
}
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> rest of ObjectCodec methods
/**********************************************************
*/
@Override
public <T> T treeToValue(TreeNode n, Class<T> valueType)
throws JsonProcessingException
{
try {
return readValue(treeAsTokens(n), valueType);
} catch (JsonProcessingException e) {
throw e;
} catch (IOException e) { // should not occur, no real i/o...
throw new IllegalArgumentException(e.getMessage(), e);
}
}
@Override
public void writeValue(JsonGenerator jgen, Object value) throws IOException, JsonProcessingException
{
throw new UnsupportedOperationException("Not implemented for ObjectReader");
}
/*
/**********************************************************
/* Helper methods, data-binding
/**********************************************************
*/
/**
* Actual implementation of value reading+binding operation.
*/
protected Object _bind(JsonParser jp, Object valueToUpdate)
throws IOException, JsonParseException, JsonMappingException
{
/* First: may need to read the next token, to initialize state (either
* before first read from parser, or after previous token has been cleared)
*/
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
if (valueToUpdate == null) {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
result = _findRootDeserializer(ctxt, _valueType).getNullValue();
} else {
result = valueToUpdate;
}
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = valueToUpdate;
} else { // pointing to event other than null
DeserializationContext ctxt = createDeserializationContext(jp, _config);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, _valueType);
if (_unwrapRoot) {
result = _unwrapAndDeserialize(jp, ctxt, _valueType, deser);
} else {
if (valueToUpdate == null) {
result = deser.deserialize(jp, ctxt);
} else {
deser.deserialize(jp, ctxt, valueToUpdate);
result = valueToUpdate;
}
}
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
}
protected Object _bindAndClose(JsonParser jp, Object valueToUpdate)
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> throws IOException, JsonParseException, JsonMappingException
{
if (_schema != null) {
jp.setSchema(_schema);
}
try {
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
if (valueToUpdate == null) {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
result = _findRootDeserializer(ctxt, _valueType).getNullValue();
} else {
result = valueToUpdate;
}
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = valueToUpdate;
} else {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, _valueType);
if (_unwrapRoot) {
result = _unwrapAndDeserialize(jp, ctxt, _valueType, deser);
} else {
if (valueToUpdate == null) {
result = deser.deserialize(jp, ctxt);
} else {
deser.deserialize(jp, ctxt, valueToUpdate);
result = valueToUpdate;
}
}
}
return result;
} finally {
try {
jp.close();
} catch (IOException ioe) { }
}
}
protected JsonNode _bindAsTree(JsonParser jp)
throws IOException, JsonParseException, JsonMappingException
{
JsonNode result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL || t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = NullNode.instance;
} else {
DeserializationContext ctxt = createDeserializationContext(jp, _config);
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, JSON_NODE_TYPE);
if (_unwrapRoot) {
result = (JsonNode) _unwrapAndDeserialize(jp, ctxt, JSON_NODE_TYPE, deser);
} else {
result = (JsonNode) deser.deserialize(jp, ctxt);
}
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
}
protected JsonNode _bindAndCloseAsTree(JsonParser jp)
throws IOException, JsonParseException, JsonMappingException
{
if (_schema
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> != null) {
jp.setSchema(_schema);
}
try {
return _bindAsTree(jp);
} finally {
try {
jp.close();
} catch (IOException ioe) { }
}
}
/**
* @since 2.1
*/
protected <T> MappingIterator<T> _bindAndReadValues(JsonParser p,
Object valueToUpdate)
throws IOException, JsonProcessingException
{
if (_schema != null) {
p.setSchema(_schema);
}
p.nextToken();
DeserializationContext ctxt = createDeserializationContext(p, _config);
return new MappingIterator<T>(_valueType, p, ctxt,
_findRootDeserializer(ctxt, _valueType),
true, _valueToUpdate);
}
protected static JsonToken _initForReading(JsonParser jp)
throws IOException, JsonParseException, JsonMappingException
{
/* First: must point to a token; if not pointing to one, advance.
* This occurs before first read from JsonParser, as well as
* after clearing of current token.
*/
JsonToken t = jp.getCurrentToken();
if (t == null) { // and then we must get something...
t = jp.nextToken();
if (t == null) {
/* [JACKSON-546] Throw mapping exception, since it's failure to map,
* not an actual parsing problem
*/
throw JsonMappingException.from(jp, "No content to map due to end-of-input");
}
}
return t;
}
/**
* Method called to locate deserializer for the passed root-level value.
*/
protected JsonDeserializer<Object> _findRootDeserializer(DeserializationContext ctxt,
JavaType valueType)
throws JsonMappingException
{
if (_rootDeserializer != null) {
return _rootDeserializer;
}
// Sanity check: must have actual type...
if (valueType == null) {
throw new JsonMappingException("No value type configured for ObjectReader");
}
// First: have we already seen it?
JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);
if (deser != null) {
return deser;
}
// Nope: need to ask provider to resolve it
deser = ctxt.findRootValueDeserializer
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(valueType);
if (deser == null) { // can this happen?
throw new JsonMappingException("Can not find a deserializer for type "+valueType);
}
_rootDeserializers.put(valueType, deser);
return deser;
}
/**
* Method called to locate deserializer ahead of time, if permitted
* by configuration. Method also is NOT to throw an exception if
* access fails.
*/
protected JsonDeserializer<Object> _prefetchRootDeserializer(
DeserializationConfig config, JavaType valueType)
{
if (valueType == null || !_config.isEnabled(DeserializationFeature.EAGER_DESERIALIZER_FETCH)) {
return null;
}
// already cached?
JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);
if (deser == null) {
try {
// If not, need to resolve; for which we need a temporary context as well:
DeserializationContext ctxt = createDeserializationContext(null, _config);
deser = ctxt.findRootValueDeserializer(valueType);
if (deser != null) {
_rootDeserializers.put(valueType, deser);
}
return deser;
} catch (JsonProcessingException e) {
// need to swallow?
}
}
return deser;
}
protected Object _unwrapAndDeserialize(JsonParser jp, DeserializationContext ctxt,
JavaType rootType, JsonDeserializer<Object> deser)
throws IOException, JsonParseException, JsonMappingException
{
String expName = _config.getRootName();
if (expName == null) {
PropertyName pname = _rootNames.findRootName(rootType, _config);
expName = pname.getSimpleName();
}
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '"
+expName+"'), but "+jp.getCurrentToken());
}
if (jp.nextToken() != JsonToken.FIELD_NAME) {
throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '"
+expName+"'), but "+jp.getCurrentToken());
}
String actualName = jp.getCurrentName();
if (!expName.equals(actualName)) {
throw Json
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>MappingException.from(jp, "Root name '"+actualName+"' does not match expected ('"
+expName+"') for type "+rootType);
}
// ok, then move to value itself....
jp.nextToken();
Object result;
if (_valueToUpdate == null) {
result = deser.deserialize(jp, ctxt);
} else {
deser.deserialize(jp, ctxt, _valueToUpdate);
result = _valueToUpdate;
}
// and last, verify that we now get matching END_OBJECT
if (jp.nextToken() != JsonToken.END_OBJECT) {
throw JsonMappingException.from(jp, "Current token not END_OBJECT (to match wrapper object with root name '"
+expName+"'), but "+jp.getCurrentToken());
}
return result;
}
/*
/**********************************************************
/* Internal methods, format auto-detection (since 2.1)
/**********************************************************
*/
@SuppressWarnings("resource")
protected Object _detectBindAndClose(byte[] src, int offset, int length) throws IOException
{
DataFormatReaders.Match match = _dataFormatReaders.findFormat(src, offset, length);
if (!match.hasMatch()) {
_reportUnkownFormat(_dataFormatReaders, match);
}
JsonParser jp = match.createParserWithMatch();
return match.getReader()._bindAndClose(jp, _valueToUpdate);
}
@SuppressWarnings("resource")
protected Object _detectBindAndClose(DataFormatReaders.Match match, boolean forceClosing)
throws IOException
{
if (!match.hasMatch()) {
_reportUnkownFormat(_dataFormatReaders, match);
}
JsonParser p = match.createParserWithMatch();
// One more thing: we Own the input stream now; and while it's
// not super clean way to do it, we must ensure closure so:
if (forceClosing) {
p.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
}
// important: use matching ObjectReader (may not be 'this')
return match.getReader()._bindAndClose(p, _valueToUpdate);
}
@SuppressWarnings("resource")
protected <T> MappingIterator<T> _detectBindAndReadValues(DataFormatReaders.Match
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> the "value method" was annotated with
* {@link com.fasterxml.jackson.databind.annotation.JsonSerialize#using}), otherwise
* null
*/
public JsonValueSerializer(Method valueMethod, JsonSerializer<Object> ser)
{
super(Object.class);
_accessorMethod = valueMethod;
_valueSerializer = ser;
_property = null;
_forceTypeInformation = true; // gets reconsidered when we are contextualized
}
@SuppressWarnings("unchecked")
public JsonValueSerializer(JsonValueSerializer src, BeanProperty property,
JsonSerializer<?> ser, boolean forceTypeInfo)
{
super(_notNullClass(src.handledType()));
_accessorMethod = src._accessorMethod;
_valueSerializer = (JsonSerializer<Object>) ser;
_property = property;
_forceTypeInformation = forceTypeInfo;
}
@SuppressWarnings("unchecked")
private final static Class<Object> _notNullClass(Class<?> cls) {
return (cls == null) ? Object.class : (Class<Object>) cls;
}
public JsonValueSerializer withResolved(BeanProperty property,
JsonSerializer<?> ser, boolean forceTypeInfo)
{
if (_property == property && _valueSerializer == ser
&& forceTypeInfo == _forceTypeInformation) {
return this;
}
return new JsonValueSerializer(this, property, ser, forceTypeInfo);
}
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
/**
* We can try to find the actual serializer for value, if we can
* statically figure out what the result type must be.
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
JsonSerializer<?> ser = _valueSerializer;
if (ser == null) {
/* Can only assign serializer statically if the declared type is final:
* if not, we don't really know the actual type until we get the instance.
*/
// 10-Mar-2010, tatu: Except if static typing is to be used
if (provider.isEnabled(MapperFeature.USE_STATIC_TYPING)
|| Modifier.isFinal(_accessorMethod.getReturnType().getModifiers())) {
JavaType t = provider.constructType(_accessorMethod.getGenericReturnType());
// false -> no need
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> to cache
/* 10-Mar-2010, tatu: Ideally we would actually separate out type
* serializer from value serializer; but, alas, there's no access
* to serializer factory at this point...
*/
// 05-Sep-2013, tatu: I _think_ this can be considered a primary property...
ser = provider.findPrimaryPropertySerializer(t, _property);
/* 09-Dec-2010, tatu: Turns out we must add special handling for
* cases where "native" (aka "natural") type is being serialized,
* using standard serializer
*/
boolean forceTypeInformation = isNaturalTypeWithStdHandling(t.getRawClass(), ser);
return withResolved(property, ser, forceTypeInformation);
}
} else {
// 05-Sep-2013, tatu: I _think_ this can be considered a primary property...
ser = provider.handlePrimaryContextualization(ser, property);
return withResolved(property, ser, _forceTypeInformation);
}
return this;
}
/*
/**********************************************************
/* Actual serialization
/**********************************************************
*/
@Override
public void serialize(Object bean, JsonGenerator jgen, SerializerProvider prov)
throws IOException, JsonGenerationException
{
try {
Object value = _accessorMethod.invoke(bean);
if (value == null) {
prov.defaultSerializeNull(jgen);
return;
}
JsonSerializer<Object> ser = _valueSerializer;
if (ser == null) {
Class<?> c = value.getClass();
/* 10-Mar-2010, tatu: Ideally we would actually separate out type
* serializer from value serializer; but, alas, there's no access
* to serializer factory at this point...
*/
// let's cache it, may be needed soon again
ser = prov.findTypedValueSerializer(c, true, _property);
}
ser.serialize(value, jgen, prov);
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t = e;
// Need to unwrap this specific type, to see infinite recursion...
while (t instanceof InvocationTargetException
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> && t.getCause() != null) {
t = t.getCause();
}
// Errors shouldn't be wrapped (and often can't, as well)
if (t instanceof Error) {
throw (Error) t;
}
// let's try to indicate the path best we can...
throw JsonMappingException.wrapWithPath(t, bean, _accessorMethod.getName() + "()");
}
}
@Override
public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer0)
throws IOException, JsonProcessingException
{
// Regardless of other parts, first need to find value to serialize:
Object value = null;
try {
value = _accessorMethod.invoke(bean);
// and if we got null, can also just write it directly
if (value == null) {
provider.defaultSerializeNull(jgen);
return;
}
JsonSerializer<Object> ser = _valueSerializer;
if (ser == null) { // already got a serializer? fabulous, that be easy...
// ser = provider.findTypedValueSerializer(value.getClass(), true, _property);
ser = provider.findValueSerializer(value.getClass(), _property);
} else {
/* 09-Dec-2010, tatu: To work around natural type's refusal to add type info, we do
* this (note: type is for the wrapper type, not enclosed value!)
*/
if (_forceTypeInformation) {
typeSer0.writeTypePrefixForScalar(bean, jgen);
ser.serialize(value, jgen, provider);
typeSer0.writeTypeSuffixForScalar(bean, jgen);
return;
}
}
/* 13-Feb-2013, tatu: Turns out that work-around should NOT be required
* at all; it would not lead to correct behavior (as per #167).
*/
// and then redirect type id lookups
// TypeSerializer typeSer = new TypeSerializerWrapper(typeSer0, bean);
ser.serializeWithType(value, jgen, provider, typeSer0);
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
Throwable t
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> = e;
// Need to unwrap this specific type, to see infinite recursion...
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors shouldn't be wrapped (and often can't, as well)
if (t instanceof Error) {
throw (Error) t;
}
// let's try to indicate the path best we can...
throw JsonMappingException.wrapWithPath(t, bean, _accessorMethod.getName() + "()");
}
}
@SuppressWarnings("deprecation")
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
if (_valueSerializer instanceof SchemaAware) {
return ((SchemaAware)_valueSerializer).getSchema(provider, null);
}
return com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonSerializer<Object> ser = _valueSerializer;
if (ser == null) {
if (typeHint == null) {
if (_property != null) {
typeHint = _property.getType();
}
if (typeHint == null) {
typeHint = visitor.getProvider().constructType(_accessorMethod.getReturnType());
}
}
ser = visitor.getProvider().findTypedValueSerializer(typeHint, false, _property);
if (ser == null) {
visitor.expectAnyFormat(typeHint);
return;
}
}
ser.acceptJsonFormatVisitor(visitor, null);
}
protected boolean isNaturalTypeWithStdHandling(Class<?> rawType, JsonSerializer<?> ser)
{
// First: do we have a natural type being handled?
if (rawType.isPrimitive()) {
if (rawType != Integer.TYPE && rawType != Boolean.TYPE && rawType != Double.TYPE) {
return false;
}
} else {
if (rawType != String.class &&
rawType != Integer.class && rawType != Boolean.class && rawType != Double.class) {
return false;
}
}
return isDefaultSerializer(ser);
}
/*
/**********************************************************
/* Other methods
/**********************************************************
*/
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.util;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import java.lang.reflect.Method;
import java.util.*;
/**
* Helper class used to resolve String values (either JSON Object field
* names or regular String values) into Java Enum instances.
*/
public class EnumResolver<T extends Enum<T>> implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected final Class<T> _enumClass;
protected final T[] _enums;
protected final HashMap<String, T> _enumsById;
protected EnumResolver(Class<T> enumClass, T[] enums, HashMap<String, T> map)
{
_enumClass = enumClass;
_enums = enums;
_enumsById = map;
}
/**
* Factory method for constructing resolver that maps from Enum.name() into
* Enum value
*/
public static <ET extends Enum<ET>> EnumResolver<ET> constructFor(Class<ET> enumCls, AnnotationIntrospector ai)
{
ET[] enumValues = enumCls.getEnumConstants();
if (enumValues == null) {
throw new IllegalArgumentException("No enum constants for class "+enumCls.getName());
}
HashMap<String, ET> map = new HashMap<String, ET>();
for (ET e : enumValues) {
map.put(ai.findEnumValue(e), e);
}
return new EnumResolver<ET>(enumCls, enumValues, map);
}
/**
* Factory method for constructing resolver that maps from Enum.toString() into
* Enum value
*/
public static <ET extends Enum<ET>> EnumResolver<ET> constructUsingToString(Class<ET> enumCls)
{
ET[] enumValues = enumCls.getEnumConstants();
HashMap<String, ET> map = new HashMap<String, ET>();
// from last to first, so that in case of duplicate values, first wins
for (int i = enumValues.length; --i >= 0; ) {
ET e = enumValues[i];
map.put(e.toString(), e);
}
return new EnumResolver<ET>(enumCls, enumValues, map);
}
public static <ET extends Enum<ET>> EnumResolver
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS><ET> constructUsingMethod(Class<ET> enumCls,
Method accessor)
{
ET[] enumValues = enumCls.getEnumConstants();
HashMap<String, ET> map = new HashMap<String, ET>();
// from last to first, so that in case of duplicate values, first wins
for (int i = enumValues.length; --i >= 0; ) {
ET en = enumValues[i];
try {
Object o = accessor.invoke(en);
if (o != null) {
map.put(o.toString(), en);
}
} catch (Exception e) {
throw new IllegalArgumentException("Failed to access @JsonValue of Enum value "+en+": "+e.getMessage());
}
}
return new EnumResolver<ET>(enumCls, enumValues, map);
}
/**
* This method is needed because of the dynamic nature of constructing Enum
* resolvers.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static EnumResolver<?> constructUnsafe(Class<?> rawEnumCls, AnnotationIntrospector ai)
{
/* This is oh so wrong... but at least ugliness is mostly hidden in just
* this one place.
*/
Class<Enum> enumCls = (Class<Enum>) rawEnumCls;
return constructFor(enumCls, ai);
}
/**
* Method that needs to be used instead of {@link #constructUsingToString}
* if static type of enum is not known.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static EnumResolver<?> constructUnsafeUsingToString(Class<?> rawEnumCls)
{
// oh so wrong... not much that can be done tho
Class<Enum> enumCls = (Class<Enum>) rawEnumCls;
return constructUsingToString(enumCls);
}
/**
* Method used when actual String serialization is indicated using @JsonValue
* on a method.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static EnumResolver<?> constructUnsafeUsingMethod(Class<?> rawEnumCls, Method accessor)
{
// wrong as ever but:
Class<Enum> enumCls = (Class<Enum>) rawEnumCls;
return constructUsingMethod(enumCls, accessor);
}
public T findEnum(String key) { return _enums
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>ById.get(key); }
public T getEnum(int index) {
if (index < 0 || index >= _enums.length) {
return null;
}
return _enums[index];
}
public List<T> getEnums() {
ArrayList<T> enums = new ArrayList<T>(_enums.length);
for (T e : _enums) {
enums.add(e);
}
return enums;
}
public Class<T> getEnumClass() { return _enumClass; }
public int lastValidIndex() { return _enums.length-1; }
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> boolean canCreateFromInt() {
return (_fromIntCreator != null);
}
@Override
public boolean canCreateFromLong() {
return (_fromLongCreator != null);
}
@Override
public boolean canCreateFromDouble() {
return (_fromDoubleCreator != null);
}
@Override
public boolean canCreateFromBoolean() {
return (_fromBooleanCreator != null);
}
@Override
public boolean canCreateUsingDefault() {
return (_defaultCreator != null);
}
@Override
public boolean canCreateUsingDelegate() {
return _delegateType != null;
}
@Override
public boolean canCreateFromObjectWith() {
return (_withArgsCreator != null);
}
@Override
public JavaType getDelegateType(DeserializationConfig config) {
return _delegateType;
}
@Override
public SettableBeanProperty[] getFromObjectArguments(DeserializationConfig config) {
return _constructorArguments;
}
/*
/**********************************************************
/* Public API implementation; instantiation from JSON Object
/**********************************************************
*/
@Override
public Object createUsingDefault(DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_defaultCreator == null) { // sanity-check; caller should check
throw new IllegalStateException("No default constructor for "+getValueTypeDesc());
}
try {
return _defaultCreator.call();
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
} catch (Exception e) {
throw wrapException(e);
}
}
@Override
public Object createFromObjectWith(DeserializationContext ctxt, Object[] args)
throws IOException, JsonProcessingException
{
if (_withArgsCreator == null) { // sanity-check; caller should check
throw new IllegalStateException("No with-args constructor for "+getValueTypeDesc());
}
try {
return _withArgsCreator.call(args);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
} catch (Exception e) {
throw wrapException(e);
}
}
@Override
public Object createUsingDelegate(DeserializationContext ctxt, Object delegate)
throws IOException, JsonProcessingException
{
if (_delegateCreator == null) { // sanity-check; caller should check
throw new IllegalStateException("No delegate constructor for "+getValueTypeDesc());
}
try {
// First simple
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> case: just delegate, no injectables
if (_delegateArguments == null) {
return _delegateCreator.call1(delegate);
}
// And then the case with at least one injectable...
final int len = _delegateArguments.length;
Object[] args = new Object[len];
for (int i = 0; i < len; ++i) {
CreatorProperty prop = _delegateArguments[i];
if (prop == null) { // delegate
args[i] = delegate;
} else { // nope, injectable:
args[i] = ctxt.findInjectableValue(prop.getInjectableValueId(), prop, null);
}
}
// and then try calling with full set of arguments
return _delegateCreator.call(args);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
} catch (Exception e) {
throw wrapException(e);
}
}
/*
/**********************************************************
/* Public API implementation; instantiation from JSON scalars
/**********************************************************
*/
@Override
public Object createFromString(DeserializationContext ctxt, String value)
throws IOException, JsonProcessingException
{
if (_fromStringCreator != null) {
try {
return _fromStringCreator.call1(value);
} catch (Exception e) {
throw wrapException(e);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
}
}
return _createFromStringFallbacks(ctxt, value);
}
@Override
public Object createFromInt(DeserializationContext ctxt, int value)
throws IOException, JsonProcessingException
{
try {
// First: "native" int methods work best:
if (_fromIntCreator != null) {
return _fromIntCreator.call1(Integer.valueOf(value));
}
// but if not, can do widening conversion
if (_fromLongCreator != null) {
return _fromLongCreator.call1(Long.valueOf(value));
}
} catch (Exception e) {
throw wrapException(e);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
}
throw ctxt.mappingException("Can not instantiate value of type "+getValueTypeDesc()
+" from Integral number ("+value+"); no single-int-arg constructor/factory
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS> method");
}
@Override
public Object createFromLong(DeserializationContext ctxt, long value)
throws IOException, JsonProcessingException
{
try {
if (_fromLongCreator != null) {
return _fromLongCreator.call1(Long.valueOf(value));
}
} catch (Exception e) {
throw wrapException(e);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
}
throw ctxt.mappingException("Can not instantiate value of type "+getValueTypeDesc()
+" from Long integral number ("+value+"); no single-long-arg constructor/factory method");
}
@Override
public Object createFromDouble(DeserializationContext ctxt, double value)
throws IOException, JsonProcessingException
{
try {
if (_fromDoubleCreator != null) {
return _fromDoubleCreator.call1(Double.valueOf(value));
}
} catch (Exception e) {
throw wrapException(e);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
}
throw ctxt.mappingException("Can not instantiate value of type "+getValueTypeDesc()
+" from Floating-point number ("+value+"); no one-double/Double-arg constructor/factory method");
}
@Override
public Object createFromBoolean(DeserializationContext ctxt, boolean value)
throws IOException, JsonProcessingException
{
try {
if (_fromBooleanCreator != null) {
return _fromBooleanCreator.call1(Boolean.valueOf(value));
}
} catch (Exception e) {
throw wrapException(e);
} catch (ExceptionInInitializerError e) {
throw wrapException(e);
}
throw ctxt.mappingException("Can not instantiate value of type "+getValueTypeDesc()
+" from Boolean value ("+value+"); no single-boolean/Boolean-arg constructor/factory method");
}
/*
/**********************************************************
/* Extended API: configuration mutators, accessors
/**********************************************************
*/
@Override
public AnnotatedWithParams getDelegateCreator() {
return _delegateCreator;
}
@Override
public AnnotatedWithParams getDefaultCreator() {
return _defaultCreator;
}
@Override
public AnnotatedWithParams getWithArgsCreator() {
return _withArgsCreator;
}
@Override
public AnnotatedParameter getIncomplete
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Parameter() {
return _incompleteParameter;
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected JsonMappingException wrapException(Throwable t)
{
while (t.getCause() != null) {
t = t.getCause();
}
if (t instanceof JsonMappingException) {
return (JsonMappingException) t;
}
return new JsonMappingException("Instantiation of "+getValueTypeDesc()+" value failed: "+t.getMessage(), t);
}
}
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.util.NameTransformer;
/**
* Deserializer that builds on basic {@link BeanDeserializer} but
* override some aspects like instance construction.
*/
public class ThrowableDeserializer
extends BeanDeserializer
{
private static final long serialVersionUID = 1L;
protected final static String PROP_NAME_MESSAGE = "message";
/*
/************************************************************
/* Construction
/************************************************************
*/
public ThrowableDeserializer(BeanDeserializer baseDeserializer) {
super(baseDeserializer);
// need to disable this, since we do post-processing
_vanillaProcessing = false;
}
/**
* Alternative constructor used when creating "unwrapping" deserializers
*/
protected ThrowableDeserializer(BeanDeserializer src, NameTransformer unwrapper) {
super(src, unwrapper);
}
@Override
public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper) {
if (getClass() != ThrowableDeserializer.class) {
return this;
}
/* main thing really is to just enforce ignoring of unknown
* properties; since there may be multiple unwrapped values
* and properties for all may be interleaved...
*/
return new ThrowableDeserializer(this, unwrapper);
}
/*
/************************************************************
/* Overridden methods
/************************************************************
*/
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// 30-Sep-2010, tatu: Need to allow use of @JsonCreator, so:
if (_propertyBasedCreator != null) { // proper @JsonCreator
return _deserializeUsingPropertyBased(jp, ctxt);
}
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt,
_delegateDeserializer.deserialize(jp, ctxt));
}
if (_beanType.isAbstract()) { // for good measure, check this too
throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_bean
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Type
+" (need to add/enable type information?)");
}
boolean hasStringCreator = _valueInstantiator.canCreateFromString();
boolean hasDefaultCtor = _valueInstantiator.canCreateUsingDefault();
// and finally, verify we do have single-String arg constructor (if no @JsonCreator)
if (!hasStringCreator && !hasDefaultCtor) {
throw new JsonMappingException("Can not deserialize Throwable of type "+_beanType
+" without having a default contructor, a single-String-arg constructor; or explicit @JsonCreator");
}
Object throwable = null;
Object[] pending = null;
int pendingIx = 0;
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
SettableBeanProperty prop = _beanProperties.find(propName);
jp.nextToken(); // to point to field value
if (prop != null) { // normal case
if (throwable != null) {
prop.deserializeAndSet(jp, ctxt, throwable);
continue;
}
// nope; need to defer
if (pending == null) {
int len = _beanProperties.size();
pending = new Object[len + len];
}
pending[pendingIx++] = prop;
pending[pendingIx++] = prop.deserialize(jp, ctxt);
continue;
}
// Maybe it's "message"?
if (PROP_NAME_MESSAGE.equals(propName)) {
if (hasStringCreator) {
throwable = _valueInstantiator.createFromString(ctxt, jp.getText());
// any pending values?
if (pending != null) {
for (int i = 0, len = pendingIx; i < len; i += 2) {
prop = (SettableBeanProperty)pending[i];
prop.set(throwable, pending[i+1]);
}
pending = null;
}
continue;
}
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
jp.skipChildren();
continue;
}
if (_anySetter != null) {
_anySetter.deserializeAndSet(
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>, -1);
} else if (_currToken == JsonToken.START_ARRAY) {
_parsingContext = _parsingContext.createChildArrayContext(-1, -1);
} else if (_currToken == JsonToken.END_OBJECT
|| _currToken == JsonToken.END_ARRAY) {
// Closing JSON Object/Array? Close matching context
_parsingContext = _parsingContext.getParent();
// but allow unbalanced cases too (more close markers)
if (_parsingContext == null) {
_parsingContext = JsonReadContext.createRootContext(null);
}
}
return _currToken;
}
@Override
public boolean isClosed() { return _closed; }
/*
/**********************************************************
/* Public API, token accessors
/**********************************************************
*/
@Override
public JsonStreamContext getParsingContext() { return _parsingContext; }
@Override
public JsonLocation getTokenLocation() { return getCurrentLocation(); }
@Override
public JsonLocation getCurrentLocation() {
return (_location == null) ? JsonLocation.NA : _location;
}
@Override
public String getCurrentName() { return _parsingContext.getCurrentName(); }
@Override
public void overrideCurrentName(String name)
{
// Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing:
JsonReadContext ctxt = _parsingContext;
if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
ctxt = ctxt.getParent();
}
try {
ctxt.setCurrentName(name);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/*
/**********************************************************
/* Public API, access to token information, text
/**********************************************************
*/
@Override
public String getText()
{
// common cases first:
if (_currToken == JsonToken.VALUE_STRING
|| _currToken == JsonToken.FIELD_NAME) {
Object ob = _currentObject();
if (ob instanceof String) {
return (String) ob;
}
return (ob == null) ? null : ob.toString();
}
if (_currToken == null) {
return null;
}
switch (_currToken) {
case VALUE_NUMBER_INT:
case VALUE_NUMBER
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>
// static if explicitly requested, or if element type is final
_staticTyping = staticTyping || (et != null && et.isFinal());
_valueTypeSerializer = vts;
_property = property;
_elementSerializer = elementSerializer;
_dynamicSerializers = PropertySerializerMap.emptyMap();
}
@SuppressWarnings("unchecked")
protected AsArraySerializerBase(AsArraySerializerBase<?> src,
BeanProperty property, TypeSerializer vts, JsonSerializer<?> elementSerializer)
{
super(src);
_elementType = src._elementType;
_staticTyping = src._staticTyping;
_valueTypeSerializer = vts;
_property = property;
_elementSerializer = (JsonSerializer<Object>) elementSerializer;
_dynamicSerializers = src._dynamicSerializers;
}
public abstract AsArraySerializerBase<T> withResolved(BeanProperty property,
TypeSerializer vts, JsonSerializer<?> elementSerializer);
/*
/**********************************************************
/* Post-processing
/**********************************************************
*/
/**
* This method is needed to resolve contextual annotations like
* per-property overrides, as well as do recursive call
* to <code>createContextual</code> of content serializer, if
* known statically.
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
TypeSerializer typeSer = _valueTypeSerializer;
if (typeSer != null) {
typeSer = typeSer.forProperty(property);
}
/* 29-Sep-2012, tatu: Actually, we need to do much more contextual
* checking here since we finally know for sure the property,
* and it may have overrides
*/
JsonSerializer<?> ser = null;
// First: if we have a property, may have property-annotation overrides
if (property != null) {
AnnotatedMember m = property.getMember();
if (m != null) {
Object serDef = provider.getAnnotationIntrospector().findContentSerializer(m);
if (serDef != null) {
ser = provider.serializerInstance(m, serDef);
}
}
}
if (ser == null) {
ser = _elementSerializer;
}
// 18-Feb-2013, tatu: May have a
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>(value, jgen, provider);
typeSer.writeTypeSuffixForArray(value, jgen);
}
protected abstract void serializeContents(T value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException;
@SuppressWarnings("deprecation")
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint)
throws JsonMappingException
{
/* 15-Jan-2010, tatu: This should probably be rewritten, given that
* more information about content type is actually being explicitly
* passed. So there should be less need to try to re-process that
* information.
*/
ObjectNode o = createSchemaNode("array", true);
JavaType contentType = null;
if (typeHint != null) {
JavaType javaType = provider.constructType(typeHint);
contentType = javaType.getContentType();
if (contentType == null) { // could still be parametrized (Iterators)
if (typeHint instanceof ParameterizedType) {
Type[] typeArgs = ((ParameterizedType) typeHint).getActualTypeArguments();
if (typeArgs.length == 1) {
contentType = provider.constructType(typeArgs[0]);
}
}
}
}
if (contentType == null && _elementType != null) {
contentType = _elementType;
}
if (contentType != null) {
JsonNode schemaNode = null;
// 15-Oct-2010, tatu: We can't serialize plain Object.class; but what should it produce here? Untyped?
if (contentType.getRawClass() != Object.class) {
JsonSerializer<Object> ser = provider.findValueSerializer(contentType, _property);
if (ser instanceof SchemaAware) {
schemaNode = ((SchemaAware) ser).getSchema(provider, null);
}
}
if (schemaNode == null) {
schemaNode = com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
}
o.put("items", schemaNode);
}
return o;
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonArrayFormatVisitor arrayVisitor = (visitor == null) ? null : visitor.expectArray
JacksonDatabind, 4
<FILEB>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<CHANGES>
try {
<CHANGEE>
<CHANGES>
} catch (Exception e) {
<CHANGEE>
<CHANGES>
throw JsonMappingException.wrapWithPath(e, String.class, ix);
}
<CHANGEE>
<FILEE>
<FILEB>
protected StringArrayDeserializer(JsonDeserializer<?> deser) {
super(String[].class);
_elementDeserializer = (JsonDeserializer<String>) deser;
}
@Override
public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
// Ok: must point to START_ARRAY (or equivalent)
if (!jp.isExpectedStartArrayToken()) {
return handleNonArray(jp, ctxt);
}
if (_elementDeserializer != null) {
return _deserializeCustom(jp, ctxt);
}
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value;
if (t == JsonToken.VALUE_STRING) {
value = jp.getText();
} else if (t == JsonToken.VALUE_NULL) {
value = null; // since we have established that '_elementDeserializer == null' earlier
} else {
value = _parseString(jp, ctxt);
}
if (ix >= chunk.length) {
chunk = buffer.appendCompletedChunk(chunk);
ix = 0;
}
chunk[ix++] = value;
}
<CHANGES>
<CHANGEE>
// note: pass String.class, not String[].class, as we need element type for error info
<CHANGES>
<CHANGEE>
String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class);
ctxt.returnObjectBuffer(buffer);
return result;
}
/**
* Offlined version used when we do not use the default deserialization method.
*/
protected final String[] _deserializeCustom(JsonParser jp, DeserializationContext ctxt) throws IOException
{
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] chunk = buffer.resetAndStart();
final JsonDeserializer<String> deser = _elementDeserializer;
int ix = 0;
JsonToken t;
<CHANGES>
<CHANGEE>
while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
// Ok: no need to convert Strings, but must recognize nulls
String value = (t == JsonToken.VALUE_NULL) ? deser.get<SCANS>Format(typeHint);
if (arrayVisitor != null) {
TypeFactory tf = visitor.getProvider().getTypeFactory();
JavaType contentType = tf.moreSpecificType(_elementType, typeHint.getContentType());
if (contentType == null) {
throw new JsonMappingException("Could not resolve type");
}
JsonSerializer<?> valueSer = _elementSerializer;
if (valueSer == null) {
valueSer = visitor.getProvider().findValueSerializer(contentType, _property);
}
arrayVisitor.itemsFormat(valueSer, contentType);
}
}
protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
Class<?> type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
// did we get a new map of serializers? If so, start using it
if (map != result.map) {
_dynamicSerializers = result.map;
}
return result.serializer;
}
protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
JavaType type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
if (map != result.map) {
_dynamicSerializers = result.map;
}
return result.serializer;
}
}